Gossamer Forum
Home : Products : Gossamer Links : Development, Plugins and Globals :

manage attachments from incoming mail (GT::Mail)

Quote Reply
manage attachments from incoming mail (GT::Mail)
Wondering...

I'm desperately trying to create a funcion to process and save attachments from incoing mail via GT:Mail. Currently I set up a working routine that retrieve mail but I've still to figure out how to manage attachments.

Does GT::Mail support this feature?

Does someone can gove me a direction to follow?



Ciao ciao

lepo
Lepo
Quote Reply
Re: [Lepo75] manage attachments from incoming mail (GT::Mail) In reply to
Hi,

Yes, GT::Mail supports this. You may want to install the forum and then the MailArc plugin, it has some code showing parsing out attachments.

It's a little tricky as html mail will show up as having two attachments, a text/plain part, and a text/html part. Trying to separate that from a text/plain message with an attached html file is fun. =)

Cheers,

Alex
--
Gossamer Threads Inc.
Quote Reply
Re: [Alex] manage attachments from incoming mail (GT::Mail) In reply to
Thank you Alex for your great help.

Question:

(from MailArc.pm) sub get_body

Code:
# No text/plain part, maybe we have an html only message.
if ( !$body ) {
for (@$parts) {
my $attach = lc $_->mime_attr('content-disposition') || '';
my $type = lc $_->mime_attr('content-type') || '';
next if ($attach eq 'attachment');
if ($type eq 'text/html') {
$body = $_->body_as_string;
last;
}
}
}


If I understood ... if you don't find the body in the main part you go through each sub-part looking for HTML ignoring attachments. ... if HTML is found you get it.

The result is a plain text without any attach.

Why you don't save attachments?



ciao ciao



lepo Tongue
Lepo
Quote Reply
Re: [Lepo75] manage attachments from incoming mail (GT::Mail) In reply to
Hi,

There is some poor naming in that subroutine. If you see above, we already have gone through all the parts and added all the attachments to @attachments. So now we just go through one more time looking for a text/html part as we didn't find a text/plain part.

Cheers,

Alex
--
Gossamer Threads Inc.
Quote Reply
Re: [Alex] manage attachments from incoming mail (GT::Mail) In reply to
Thank you alex, now all is clear.

At last but not least.. Trying to manify Html in order to fix calls for all images attached in the mail ... let say..

this attachment:

--------------040104050904040302040809
Content-Type: image/gif
Content-Transfer-Encoding: base64
Content-ID: part1.07010607.03030602@marymode.com[/code]

is called in the included html like this:

Code:
<img src="cid:part1.07010607.03030602@marymode.com" alt="" width="227" height="228">


I wondered that in GT::Mail::Parts you don't include in your header array (@HEADER) the mime_attr: Content-ID. This is the code I need to substitute.

Do I have to include it in the @HEADER array?

Ok, just to let you know Blush



thanks again



lepo
Lepo
Quote Reply
Re: [Lepo75] manage attachments from incoming mail (GT::Mail) In reply to
Hi,

You can use ->get to get the header:

my $content_id = $part->get('content-id');

and then do the matching of html to image (it's really not fun). =)

Cheers,

Alex
--
Gossamer Threads Inc.
Quote Reply
Re: [Alex] manage attachments from incoming mail (GT::Mail) In reply to
Ok, Just to let you know (may be can helps someone) I did a new recursive function that try to find a body in the mail message including also inline/attached images. These inline immages can easily be replaced in the body message.

This is not bullet proof, I mean, It would have also some mime check. But it works in almost 99% of cases.

here's the code.

Code:
sub get_body {
#--------------------------------------------------------------------
# Parse the body (@lepo's manufacure - warning :::: recursive)
# the funcion seach recursively through whole parts doing two operations: Lookin for subparts, saving attachments and documents.
# nested documents are more relevant.
# From a Head-mail object, it returns an hash with body, array-ref of all attachments and a MIME type.

my $self = shift;
my $head = shift;
my ($body, $type, $attachments);
# is a sub-parts into this part? yeah, let's do the recursive-thing.
if($head->is_multipart) {
my $parts = $head->parts;
for (@$parts) {
my $r = $self->get_body($_);
for my $attach (@{$r->{attachments}}) { push @{$attachments}, $attach ; }
# save the body and type. Remember, nested is more relevant.
($r->{body}) and ($body = $r->{body});
($r->{type}) and ($type = $r->{body});
}
}

$type = lc($head->mime_attr('content-type'));
#this check is a quite rough but is works. (?) Every MIME stat has the word 'text' means it a text, otherwise
#we save it as an attach. This it's not really a smart sub.
if (($type !~ m/text/i)) {
my ($b, $attach);
my $in = $head->body_in;
if ($in eq 'MEMORY') { $b = $head->body_data; }
elsif ($in eq 'HANDLE') { $b = $head->body_handle; }
elsif ($in eq 'FILE') { $b = $head->body_path; }
if($b) {
$attach = { 'name' => $head->recommended_filename() || $self->build_name($type),
'type' => $type || 'application/octet-stream',
'id' => $head->get('content-id'),
'file' => $b,
};
push @{$attachments}, $attach;
# print "\nname= " . $attach->{name} . " type= [" . $attach->{'type'} . "] id= " . $attach->{'id'};
}
}
else {
$body = $head->body_as_string;
}

return { body => $body, attachments => $attachments, type => $type};
} sub build_name {
#-------------------------------------------------------
# given a MIME type return an appropriate filename. Uses global
# object variable $self->{internal_counter}
my $self = shift;
my $type = shift;
my $name = $self->{internal_counter}++; SWITCH:{ $type =~ /html/i and do { $name .= '.html'; last SWITCH };
$type =~ /gif/i and do { $name .= '.gif'; last SWITCH };
$type =~ /png/i and do { $name .= '.png'; last SWITCH };
$type =~ /jpeg/i and do { $name .= '.jpg'; last SWITCH };
$type =~ /jpg/i and do { $name .= '.jpg'; last SWITCH };
$type =~ /xml/i and do { $name .= '.xml'; last SWITCH };
$type =~ /zip/i and do { $name .= '.zip'; last SWITCH };
$type =~ /xml/i and do { $name .= '.xml'; last SWITCH };
$type =~ /mpeg/i and do { $name .= '.mpeg'; last SWITCH };
$type =~ /bmp/i and do { $name .= '.bmp'; last SWITCH };
$type =~ /msword/i and do { $name .= '.doc'; last SWITCH };
$type =~ /x-shockwave-flash/i and do { $name .= '.swf'; last SWITCH };
$type =~ /ms-excel/i and do { $name .= '.xls'; last SWITCH };
}
#debug print "\n $name ($type)";
return $name;
}


hope it helps

ciaociao
Lepo

Last edited by:

Lepo75: Jun 22, 2002, 9:48 AM