#!/usr/bin/perl -w # $Id: bugzilla-email,v 1.8 2006/03/18 22:33:40 hudson Exp $ # # 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 purpose of this script is to take an email message, which # specifies a bugid and append it to the bug as part of the longdesc # table # Seriously reworked by Trammell Hudson # Originally by: Seth M. Landsman # 03/15/00 : Initial version by SML # 03/15/00 : processmail gets called # THE FORMAT OF THE EMAIL HAS CHANGED. This needs to be updated. # Email subject must be of format : # .* Bug ### .* # replying to a typical bugzilla email should be valid use FindBin; use lib "$FindBin::Bin/../lib"; use Bugzilla::OO; use warnings; use strict; use Bugzilla::BugMail; use MIME::Parser; use Data::Dumper; # Create a new MIME parser and read the message from stdin # We put the temp files in /tmp, which may be a security issue, # but of little importance right now. my $parser = new MIME::Parser; $parser->output_dir( '/tmp' ); my $entity = $parser->parse( \*STDIN ); my $parts_count = $entity->parts; # Extract the headers from the message my $headers = $entity->head; my $sender = $headers->get( 'From' ); my $subject = $headers->get( 'Subject' ); # Remove any newlines from the headers s/[\r\n]//g for $sender, $subject; # Find the bug number in the subject line # Bugs must be white-space separated my ($bugids) = $subject =~ / \[? Bug\s+ ( [^]]+ ) # Anything up to the close bracket \s* \] /x or die "No bugs in subject line? '$subject'\n"; my @bugids = split /\s+/, $bugids; # Rewrite the subject line so that any leading Re: and [Bug ...] are removed $subject =~ s/^(Re:\s*)*//; $subject =~ s/\[?Bug\s+[^]]*\]\s*//; # Extract just the email from the sender # This is a bit of a hack, since they could have < or > in their # name. We assume that it is fairly normal and that if there is # no full name then the entire sender string is the email address # to use. my ($email) = $sender =~ /<(.*\@.*)>/; $email ||= $sender; # If there is no hostname, add a default one $email .= '@osresearch.net' unless $email =~ /\@/; print STDERR "Bugs: @bugids\n"; print STDERR "Subject: $subject\n"; print STDERR "From: $sender\n"; print STDERR "Email: $email\n"; #$entity->dump_skeleton; my $body; my @attachments; # If this is a single part message, we should just append it # (To be handled later) unless( $entity->parts ) { # Single part. Just add it as a comment $body = $entity->stringify_body; } else { # Multi-part. # Assume the first part is the comment body and any additional # parts are the attachments @attachments = $entity->parts; $body = $attachments[0]->stringify_body; shift @attachments; } # # We now have the bug ids, the sender email, the subject, the body # and any attachments to create. Let's verify a few things first. # my $session = Bugzilla::OO->new( $email ) or die "$email: No such user!\n"; for(@bugids) { my ($id,$flags) = split /=/, $_, 2; my $bug = $session->get_bug( $id ) or warn "Bug $id: No such bug?\n" and next; $flags ||= ''; my $private = $flags =~ s/,?private,?//; $bug->add_comment( "Subject: $subject [$flags]\n\n" . $body, $private ); # Check for status flags for( split /,/, $flags ) { $bug->set_bug_status( $1 ) if /^(closed|assigned|resolved)$/; $bug->set_resolution( $1 ) if /^(fixed|invalid|wontfix|later|remind|worksforme)$/; $bug->set_duplicate( $1 ) if /^dupe=(\d+)$/; $bug->set_assigned_to( $1 ) if /^assigned=([^,]*)$/; } # If we have any attachments, add them # # Why doesn't MIME::Entity have an easy way to get the filename # from the header? for my $attachment ( @attachments ) { my $headers = $attachment->head; my $filename = $headers->get( 'Content-Disposition' ); $filename =~ s/.*filename="(.*)".*/$1/msg; $filename ||= 'attachment'; # Hueristicly determine if this is a patch file my $is_patch = $filename =~ /\.patch$/; $bug->add_attachment( $filename, $filename, $attachment->mime_type, $is_patch, $attachment->stringify_body ); print STDERR "$id: Added attachment ($filename)\n"; } Bugzilla::BugMail::Send( $bug->{id}, { changer => $email } ); } # Cleanup $parser->filer->purge; __END__