]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 65477: Send HTML bugmail
authorGuy Pyrzak <guy.pyrzak@gmail.com>
Sun, 3 Oct 2010 20:44:42 +0000 (13:44 -0700)
committerGuy Pyrzak <guy.pyrzak@gmail.com>
Sun, 3 Oct 2010 20:44:42 +0000 (13:44 -0700)
r=mkanat, a=mkanat

Bugzilla/BugMail.pm
Bugzilla/Template.pm
template/en/default/email/bugmail-common.txt.html [new file with mode: 0644]
template/en/default/email/bugmail-header.txt.tmpl [new file with mode: 0644]
template/en/default/email/bugmail.html.tmpl [new file with mode: 0644]
template/en/default/email/bugmail.txt.tmpl [moved from template/en/default/email/newchangedmail.txt.tmpl with 58% similarity]

index 2ac5752938c7b9def44e1ab177d5ac0ad10852ee..dfd7584ea63e4265720e1e4f6a0ea0cc61a06bd5 100644 (file)
@@ -29,6 +29,7 @@
 #                 Byron Jones <bugzilla@glob.com.au>
 #                 Reed Loden <reed@reedloden.com>
 #                 Frédéric Buclin <LpSolit@gmail.com>
+#                 Guy Pyrzak <guy.pyrzak@gmail.com>
 
 use strict;
 
@@ -83,10 +84,9 @@ sub Send {
     # can 'have' a role, if the person in that role has changed, or people are
     # watching.
     my @assignees = ($bug->assigned_to);
-    my @qa_contacts = ($bug->qa_contact);
+    my @qa_contacts = $bug->qa_contact || ();
 
     my @ccs = @{ $bug->cc_users };
-
     # Include the people passed in as being in particular roles.
     # This can include people who used to hold those roles.
     # At this point, we don't care if there are duplicates in these arrays.
@@ -104,6 +104,7 @@ sub Send {
             push(@ccs, Bugzilla::User->check($cc));
         }
     }
+    my %user_cache = map { $_->id => $_ } (@assignees, @qa_contacts, @ccs);
 
     my @diffs;
     if (!$start) {
@@ -123,7 +124,7 @@ sub Send {
                        blocker => $params->{blocker} });
     }
     else {
-        push(@diffs, _get_diffs($bug, $end));
+        push(@diffs, _get_diffs($bug, $end, \%user_cache));
     }
 
     my $comments = $bug->comments({ after => $start, to => $end });
@@ -220,7 +221,8 @@ sub Send {
     foreach my $user_id (keys %recipients) {
         my %rels_which_want;
         my $sent_mail = 0;
-        my $user = new Bugzilla::User($user_id);
+        $user_cache{$user_id} ||= new Bugzilla::User($user_id);
+        my $user = $user_cache{$user_id};
         # Deleted users must be excluded.
         next unless $user;
 
@@ -353,19 +355,47 @@ sub sendMail {
         new_comments => \@send_comments,
         threadingmarker => build_thread_marker($bug->id, $user->id, !$bug->lastdiffed),
     };
-
-    my $msg;
-    my $template = Bugzilla->template_inner($user->settings->{'lang'}->{'value'});
-    $template->process("email/newchangedmail.txt.tmpl", $vars, \$msg)
-      || ThrowTemplateError($template->error());
-
+    my $msg =  _generate_bugmail($user, $vars);
     MessageToMTA($msg);
 
     return 1;
 }
 
+sub _generate_bugmail {
+    my ($user, $vars) = @_;
+    my $template = Bugzilla->template_inner($user->settings->{'lang'}->{'value'});
+    my ($msg_text, $msg_html, $msg_header);
+  
+    $template->process("email/bugmail-header.txt.tmpl", $vars, \$msg_header)
+        || ThrowTemplateError($template->error());
+    $template->process("email/bugmail.txt.tmpl", $vars, \$msg_text)
+        || ThrowTemplateError($template->error());
+    $template->process("email/bugmail.html.tmpl", $vars, \$msg_html)
+        || ThrowTemplateError($template->error());
+    
+    my @parts = (
+        Email::MIME->create(
+            attributes => {
+                content_type => "text/plain",
+            },
+            body => $msg_text,
+        ),
+        Email::MIME->create(
+            attributes => {
+                content_type => "text/html",         
+            },
+            body => $msg_html,
+        ),
+    );
+  
+    my $email = new Email::MIME($msg_header);
+    $email->parts_set(\@parts);
+    $email->content_type_set('multipart/alternative');
+    return $email;
+}
+
 sub _get_diffs {
-    my ($bug, $end) = @_;
+    my ($bug, $end, $user_cache) = @_;
     my $dbh = Bugzilla->dbh;
 
     my @args = ($bug->id);
@@ -377,20 +407,20 @@ sub _get_diffs {
     }
 
     my $diffs = $dbh->selectall_arrayref(
-           "SELECT profiles.login_name, profiles.realname, fielddefs.name AS field_name,
+           "SELECT fielddefs.name AS field_name,
                    bugs_activity.bug_when, bugs_activity.removed AS old,
                    bugs_activity.added AS new, bugs_activity.attach_id,
-                   bugs_activity.comment_id
+                   bugs_activity.comment_id, bugs_activity.who
               FROM bugs_activity
         INNER JOIN fielddefs
                 ON fielddefs.id = bugs_activity.fieldid
-        INNER JOIN profiles
-                ON profiles.userid = bugs_activity.who
              WHERE bugs_activity.bug_id = ?
                    $when_restriction
           ORDER BY bugs_activity.bug_when", {Slice=>{}}, @args);
 
     foreach my $diff (@$diffs) {
+        $user_cache->{$diff->{who}} ||= new Bugzilla::User($diff->{who}); 
+        $diff->{who} =  $user_cache->{$diff->{who}};
         if ($diff->{attach_id}) {
             $diff->{isprivate} = $dbh->selectrow_array(
                 'SELECT isprivate FROM attachments WHERE attach_id = ?',
index 5ff5482b28cadb709fc703d729592fc85e2b9a00..ee4d6cba2573e873398643604b385f8def4512db 100644 (file)
@@ -348,8 +348,12 @@ sub get_bug_link {
     }
     # Prevent code injection in the title.
     $title = html_quote(clean_text($title));
-
     my $linkval = "show_bug.cgi?id=" . $bug->id;
+    
+    if ($options->{full_url}) {
+        $linkval = correct_urlbase() . $linkval;
+    }
+    
     if (defined $options->{comment_num}) {
         $linkval .= "#c" . $options->{comment_num};
     }
diff --git a/template/en/default/email/bugmail-common.txt.html b/template/en/default/email/bugmail-common.txt.html
new file mode 100644 (file)
index 0000000..b6cadaf
--- /dev/null
@@ -0,0 +1,38 @@
+[%# The contents of this file are subject to the Mozilla Public
+  # License Version 1.1 (the "License"); you may not use this file
+  # except in compliance with the License. You may obtain a copy of
+  # the License at http://www.mozilla.org/MPL/
+  #
+  # Software distributed under the License is distributed on an "AS
+  # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+  # implied. See the License for the specific language governing
+  # rights and limitations under the License.
+  #
+  # The Original Code is the Bugzilla Bug Tracking System.
+  #
+  # The Initial Developer of the Original Code is Guy Pyrzak
+  # Portions created by the Initial Developer are Copyright (C) 2010 the
+  # Initial Developer. All Rights Reserved.
+  #
+  # Contributor(s): Guy Pyrzak <guy.pyrzak@gmail.com>
+  #%]
+  
+[% PROCESS "global/field-descs.none.tmpl" %]
+
+[% field_label = field_descs.${change.field_name} %]
+[% old_value = display_value(change.field_name, change.old) %]
+[% new_value = display_value(change.field_name, change.new) %]
+
+[% IF change.field_name == "estimated_time" || change.field_name == "remaining_time" %]
+  [% old_value = old_value FILTER format('%.2f') %]
+  [% new_value = new_value FILTER format('%.2f') %]
+[% END %]
+
+[% IF change.attach_id %]
+  [% field_label = field_label.replace('^(Attachment )?', "Attachment #${change.attach_id} ") %]
+[% END %]
+
+[% IF change.field_name == 'longdescs.isprivate' %]
+  [% field_label = field_label.replace('^(Comment )?', "Comment #${change.num} ") %]
+[% END %]
+  
\ No newline at end of file
diff --git a/template/en/default/email/bugmail-header.txt.tmpl b/template/en/default/email/bugmail-header.txt.tmpl
new file mode 100644 (file)
index 0000000..c2b4ea4
--- /dev/null
@@ -0,0 +1,47 @@
+[%# The contents of this file are subject to the Mozilla Public
+  # License Version 1.1 (the "License"); you may not use this file
+  # except in compliance with the License. You may obtain a copy of
+  # the License at http://www.mozilla.org/MPL/
+  #
+  # Software distributed under the License is distributed on an "AS
+  # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+  # implied. See the License for the specific language governing
+  # rights and limitations under the License.
+  #
+  # The Original Code is the Bugzilla Bug Tracking System.
+  #
+  # The Initial Developer of the Original Code is Netscape Communications
+  # Corporation. Portions created by Netscape are
+  # Copyright (C) 1998 Netscape Communications Corporation. All
+  # Rights Reserved.
+  #
+  # Contributor(s): André Batosti <batosti@async.com.br>
+  #                 Frédéric Buclin <LpSolit@gmail.com>
+  #                 Guy Pyrzak <guy.pyrzak@gmail.com>
+  #%]
+  
+[% PROCESS "global/field-descs.none.tmpl" %]
+[% PROCESS "global/reason-descs.none.tmpl" %]
+[% isnew = bug.lastdiffed ? 0 : 1 %]
+
+From: [% Param('mailfrom') %]
+To: [% to_user.email %]
+Subject: [[% terms.Bug %] [%+ bug.id %]] [% 'New: ' IF isnew %][%+ bug.short_desc %]
+Date: [% delta_ts || bug.delta_ts FILTER time("%a, %d %b %Y %T %z", to_user.timezone) %]
+X-Bugzilla-Reason: [% reasonsheader %]
+X-Bugzilla-Type: [% isnew ? 'new' : 'changed' %]
+X-Bugzilla-Watch-Reason: [% reasonswatchheader %]
+[% IF Param('useclassification') %]
+X-Bugzilla-Classification: [% bug.classification %]
+[% END %]
+X-Bugzilla-Product: [% bug.product %]
+X-Bugzilla-Component: [% bug.component %]
+X-Bugzilla-Keywords: [% bug.keywords %]
+X-Bugzilla-Severity: [% bug.bug_severity %]
+X-Bugzilla-Who: [% changer.login %]
+X-Bugzilla-Status: [% bug.bug_status %]
+X-Bugzilla-Priority: [% bug.priority %]
+X-Bugzilla-Assigned-To: [% bug.assigned_to.login %]
+X-Bugzilla-Target-Milestone: [% bug.target_milestone %]
+X-Bugzilla-Changed-Fields: [% changedfields.join(" ") %]
+[%+ threadingmarker %]
diff --git a/template/en/default/email/bugmail.html.tmpl b/template/en/default/email/bugmail.html.tmpl
new file mode 100644 (file)
index 0000000..888d47b
--- /dev/null
@@ -0,0 +1,126 @@
+[%# The contents of this file are subject to the Mozilla Public
+  # License Version 1.1 (the "License"); you may not use this file
+  # except in compliance with the License. You may obtain a copy of
+  # the License at http://www.mozilla.org/MPL/
+  #
+  # Software distributed under the License is distributed on an "AS
+  # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+  # implied. See the License for the specific language governing
+  # rights and limitations under the License.
+  #
+  # The Original Code is the Bugzilla Bug Tracking System.
+  #
+  # The Initial Developer of the Original Code is Guy Pyrzak
+  # Portions created by the Initial Developer are Copyright (C) 2010 the
+  # Initial Developer. All Rights Reserved.
+  #
+  # Contributor(s): Guy Pyrzak <guy.pyrzak@gmail.com>
+  #%]
+  
+[% PROCESS "global/field-descs.none.tmpl" %]
+[% PROCESS "global/reason-descs.none.tmpl" %]
+
+[% isnew = bug.lastdiffed ? 0 : 1 %]
+<html>
+    <head>
+      <base href="[% %]" />
+    </head>
+    <body>
+      [% PROCESS generate_diffs %]
+      <p>
+      [% FOREACH comment = new_comments.reverse %]
+        <div>
+          [% IF comment.count %]
+            <b>[% "Comment # ${comment.count}" FILTER bug_link( bug, 
+              {comment_num => comment.count, full_url => 1}) FILTER none %] 
+              from [% INCLUDE global/user.html.tmpl who = comment.author %]</b>
+          [% END %]
+        <pre>[% comment.body_full({ wrap => 1 }) FILTER html %]</pre>
+        </div>
+      [% END %]
+      </p>
+      <p>
+        <a href="[% urlbase FILTER html %]userprefs.cgi?tab=email">
+          Configure [% terms.bug %]mail
+        </a>
+      </p>
+      
+      <span>You are receiving this mail because:</span>
+      
+      <ul>
+      [% FOREACH reason = reasons %]
+        [%  IF reason_descs.$reason  %]
+          <li>[% reason_descs.$reason FILTER html %]</li>
+        [% END %]
+      [% END %]
+      [% FOREACH reason = reasons_watch %]
+        [% IF watch_reason_descs.$reason %]
+          <li>[% watch_reason_descs.$reason FILTER html %]</li>
+        [% END %]
+      [% END %]
+      </ul>
+    </body>
+</html>
+
+[% BLOCK generate_diffs %]
+  
+  [% "${terms.Bug} ${bug.id}" FILTER bug_link(bug, full_url => 1) FILTER none %]
+
+  [% last_changer = "" %]
+  <table border="1" cellspacing="0" cellpadding="2">
+    [% FOREACH change = diffs %]
+      [% IF !isnew && change.who.login != last_changer %]
+        [% last_changer = change.who.login %]
+        [% IF change.blocker %]
+          <tr>
+            <td colspan="3">
+              [% "${terms.Bug} ${bug.id}" FILTER bug_link(bug, full_url => 1) FILTER none  %] depends 
+              on [% "${terms.bug} ${change.blocker.id}" 
+                  FILTER bug_link(change.blocker, full_url => 1) FILTER none %],
+              which changed state.
+          </td>
+          </tr>
+        [% ELSE %]
+          <tr>
+            <td colspan="3">
+              [% INCLUDE global/user.html.tmpl who = change.who %]
+              changed:
+            </td>
+          </tr>
+        [% END %]
+        <tr>
+          <th>What</th>
+          <th>Removed</th>
+          <th>Added</th>
+        </tr>
+      [% END %]
+
+      [% PROCESS "email/bugmail-common.txt.html" %]
+
+      [% IF isnew %]
+        <tr>
+          <th>[% field_label FILTER html %]</th>
+          <td>[% new_value FILTER html %]</td>
+        </tr>
+      [% ELSE %]
+         <tr>
+           <td style="text-align:right;">[% field_label FILTER html %]</td>
+           <td>
+             [% IF old_value %]
+               [% old_value FILTER html %]
+             [% ELSE %]
+               &nbsp;
+             [% END%]
+           </td>
+           <td>
+             [% IF new_value %]
+               [% new_value FILTER html %]
+             [% ELSE %]
+               &nbsp;
+             [% END%]
+           </td>
+         </tr>
+      [% END %]
+    [% END %]
+  </table>
+[% END %]
\ No newline at end of file
similarity index 58%
rename from template/en/default/email/newchangedmail.txt.tmpl
rename to template/en/default/email/bugmail.txt.tmpl
index de4a248e3ec2b546250023bfc720dc381200e064..31efaba3341f74314e16ece3857401cc32de7714 100644 (file)
@@ -17,6 +17,7 @@
   #
   # Contributor(s): André Batosti <batosti@async.com.br>
   #                 Frédéric Buclin <LpSolit@gmail.com>
+  #                 Guy Pyrzak <guy.pyrzak@gmail.com>
   #%]
 
 [% PROCESS "global/field-descs.none.tmpl" %]
 
 [% isnew = bug.lastdiffed ? 0 : 1 %]
 
-From: [% Param('mailfrom') %]
-To: [% to_user.email %]
-Subject: [[% terms.Bug %] [%+ bug.id %]] [% 'New: ' IF isnew %][%+ bug.short_desc %]
-Date: [% delta_ts || bug.delta_ts FILTER time("%a, %d %b %Y %T %z", to_user.timezone) %]
-X-Bugzilla-Reason: [% reasonsheader %]
-X-Bugzilla-Type: [% isnew ? 'new' : 'changed' %]
-X-Bugzilla-Watch-Reason: [% reasonswatchheader %]
-[% IF Param('useclassification') %]
-X-Bugzilla-Classification: [% bug.classification %]
-[% END %]
-X-Bugzilla-Product: [% bug.product %]
-X-Bugzilla-Component: [% bug.component %]
-X-Bugzilla-Keywords: [% bug.keywords %]
-X-Bugzilla-Severity: [% bug.bug_severity %]
-X-Bugzilla-Who: [% changer.login %]
-X-Bugzilla-Status: [% bug.bug_status %]
-X-Bugzilla-Priority: [% bug.priority %]
-X-Bugzilla-Assigned-To: [% bug.assigned_to.login %]
-X-Bugzilla-Target-Milestone: [% bug.target_milestone %]
-X-Bugzilla-Changed-Fields: [% changedfields.join(" ") %]
-[%+ threadingmarker %]
-
 [%+ PROCESS generate_diffs -%]
 
 [% FOREACH comment = new_comments %]
@@ -74,42 +53,25 @@ Configure [% terms.bug %]mail: [% urlbase %]userprefs.cgi?tab=email
 
 [%+ last_changer = "" %]
   [% FOREACH change = diffs %]
-    [% IF !isnew && change.login_name != last_changer %]
-      [% last_changer = change.login_name %]
+    [% IF !isnew && change.who.login != last_changer %]
+      [% last_changer = change.who.login %]
       [% IF change.blocker %]
         [% terms.Bug %] [%+ bug.id %] depends on [% terms.bug %] [%+ change.blocker.id %], which changed state.
 
 [%+ terms.Bug %] [%+ change.blocker.id %] Summary: [% change.blocker.short_desc %]
 [%+ urlbase %]show_bug.cgi?id=[% change.blocker.id %]
       [% ELSE %]
-        [%~ IF change.realname %]
-          [% change.realname _ " <" _ change.login_name _ ">" %]
+        [%~ IF change.who.name %]
+          [% change.who.name _ " <" _ change.who.login _ ">" %]
         [% ELSE %]
-          [% change.login_name %]
+          [% change.who.login %]
         [% END %] changed:
       [% END %]
 
            What    |Removed                     |Added
 ----------------------------------------------------------------------------
 [%+ END %][%# End of IF. This indentation is intentional! ~%]
-
-    [% field_label = field_descs.${change.field_name} %]
-    [% old_value = display_value(change.field_name, change.old) %]
-    [% new_value = display_value(change.field_name, change.new) %]
-
-    [%~ IF change.field_name == "estimated_time" || change.field_name == "remaining_time" %]
-      [% old_value = old_value FILTER format('%.2f') %]
-      [% new_value = new_value FILTER format('%.2f') %]
-    [% END %]
-
-    [%~ IF change.attach_id %]
-      [% field_label = field_label.replace('^(Attachment )?', "Attachment #${change.attach_id} ") %]
-    [% END %]
-
-    [%~ IF change.field_name == 'longdescs.isprivate' %]
-      [% field_label = field_label.replace('^(Comment )?', "Comment #${change.num} ") %]
-    [% END %]
-
+    [% PROCESS "email/bugmail-common.txt.html"%]
     [%~ IF isnew %]
       [% format_columns(2, field_label _ ":", new_value) -%]
     [% ELSE %]