Let me back up and explain why I'm doing all these crazy hijinx so you understand what I'm trying to do before I respond to your reply specifically. As you might remember I was tasked with writing a mail forwarder for our PR department and came here to ask a bunch of questions. Here's how it works:
1. People send a message they want forwarded to a particular mailbox
2. They load up my script from our intranet, and it's provided with a list of addresses to forward to.
3. They click a button next to the message in the IMAP mailbox they want to forward
4. It gets sent out with Swift.
Step 4 of course is the interesting part. The first version simply got the original message body via IMAP, figured out the MIME type, content type, transfer encoding and MIME boundary, and laboriously created a Swift message that would use all these with the existing body, then sent it off. We were then informed that to comply with US law, we'd need to insert remove links for people to click to take themselves off our mailing lists and we'd like to do a custom link each time since we're already doing per-user VERP anyway -- meaning step 4 just got more complicated, since I now have to take the message and rebuild it using Swift since I can't just search and replace in a pre-bundled message due to various encodings, etc. So that's where I'm at now.
Now my response to your reply:
Are you saying multipart/mixed itself is purely an attachment type? I don't believe so. From my understanding it's used to bundle up chunks of varying mime types to be displayed in order. Here are some examples I'm testing with now. As you can see, not everything is file data at all -- from the simplest message below, there's a text part, a PDF to be displayed inline (if possible), then another text part.
From Apple Mail:
MULTIPART/MIXED :: 7BIT
1 -- 0K :: TEXT/PLAIN :: 7BIT
2 -- 180K :: APPLICATION/PDF :: BASE64 :: Workshop PR.pdf
3 -- 0K :: TEXT/PLAIN :: 7BIT
this is forwarded as
multipart/alternative
-- multipart/mixed
---- text/plain
---- application/pdf
---- text/plain
* * *
From GMail:
MULTIPART/MIXED :: 7BIT
1 -- MULTIPART/ALTERNATIVE :: 7BIT
1.1 ---- 0K :: TEXT/PLAIN :: 7BIT
1.2 ---- 0K :: TEXT/HTML :: 7BIT
1.3 ---- 1K :: TEXT/CALENDAR :: 7BIT
2 -- 2K :: APPLICATION/ICS :: BASE64 :: invite20080519T150000.ics
3 -- 49K :: IMAGE/JPEG :: BASE64 :: lolmeerkat.jpg
forwarded as
multipart/alternative
-- multipart/mixed
---- multipart/alternative
------ text/plain
------ text/html
------ text/calendar
---- application/ics
---- image/jpeg
* * *
From Apple Mail:
MULTIPART/ALTERNATIVE :: 7BIT
1 -- 0K :: TEXT/PLAIN :: QUOTED-PRINTABLE
2 -- MULTIPART/MIXED :: 7BIT
2.1 ---- 0K :: TEXT/HTML :: 7BIT
2.2 ---- 136K :: APPLICATION/OCTET-STREAM :: BASE64 :: Workshop PR.doc
2.3 ---- 0K :: TEXT/HTML :: 7BIT
2.4 ---- 180K :: APPLICATION/PDF :: BASE64 :: Workshop PR.pdf
2.5 ---- 2K :: TEXT/HTML :: QUOTED-PRINTABLE
forwarded wrapped the same way as above
* * *
So you can see, all these messages are being wrapped in an extra multipart/alternative wrapper -- still trying to determine if that's my code or yours -- but I'd like to preserve the original MIME tree if at all possible for the simple reason that the people who wrote mailers probably know a good deal more than me about how to create MIME messages that are readable in most or all other clients, and I don't want to introduce a change to the messages that will cause people to be unable to read them.
As for the other aspect of your reply, I'm not using anything having to do with any files, even for attached files. Here's some hopefully readable code that's used to build the message for forwarding out. (The $mime_tree is essentially what you see displayed in the nice formatted printouts above. It's an array of arrays, basically in a tree structure (subtrees are in $leaf['parts']).
Code: Select all
/**
* Recurse through a mime tree and make a Swift_Message_Part of every node, including non-leaf nodes.
* However,
*/
function swiftify_mime_tree($mbox, $msgno, &$mime_tree) {
// not using array_walk_recursive due to bugs, see http://bugs.php.net/bug.php?id=42850
// $index must be used because $dummynode is a copy, not a reference :/
foreach($mime_tree as $index => $dummynode) {
if(is_array($mime_tree[$index]['parts'])) {
// recurse immediately
swiftify_mime_tree($mbox, $msgno, $mime_tree[$index]['parts']);
// now that the children of the current node have been swiftified, we wrap them up in their own Swift_Message_Part
$mime_tree[$index]['swift_part'] = new Swift_Message_Part(null, strtolower($mime_tree[$index]['mime_type']), strtolower($mime_tree[$index]['encoding']), strtolower($mime_tree[$index]['charset']));
foreach($mime_tree[$index]['parts'] as $subpart_index => $dummynode2) {
$mime_tree[$index]['swift_part']->addChild($mime_tree[$index]['parts'][$subpart_index]['swift_part']);
}
} else {
// make a part for a leaf node. the type we make is based on some attributes such as filename, disposition (inline or attachment), etc.
if($mime_tree[$index]['filename']) {
// the part has a filename, it should be attached as such
if(isset($mime_tree[$index]['id'])) {
// the part has an id (usually for embedding inline in html emails), so attach it as a swift embedded file
$mime_tree[$index]['swift_part'] = new Swift_Message_EmbeddedFile(decode_part(imap_fetchbody($mbox, $msgno, $mime_tree[$index]['pid']), strtolower($mime_tree[$index]['encoding'])),
$mime_tree[$index]['filename'],
strtolower($mime_tree[$index]['mime_type']),
$mime_tree[$index]['id'],
strtolower($mime_tree[$index]['encoding']));
} else {
// no id, just attach as an attachment with the given disposition, if any
$mime_tree[$index]['swift_part'] = new Swift_Message_Attachment(decode_part(imap_fetchbody($mbox, $msgno, $mime_tree[$index]['pid']), strtolower($mime_tree[$index]['encoding'])),
$mime_tree[$index]['filename'],
strtolower($mime_tree[$index]['mime_type']),
strtolower($mime_tree[$index]['encoding']),
$mime_tree[$index]['disposition']);
}
} else {
// don't do anything special, just attach the part as a normal message part
$mime_tree[$index]['swift_part'] = new Swift_Message_Part(decode_part(imap_fetchbody($mbox, $msgno, $mime_tree[$index]['pid']), strtolower($mime_tree[$index]['encoding'])),
strtolower($mime_tree[$index]['mime_type']),
strtolower($mime_tree[$index]['encoding']),
strtolower($mime_tree[$index]['charset']));
}
}
}
return;
}