[KLUG Members] MIME attachments

Adam Tauno Williams adam at morrison-ind.com
Wed Nov 16 15:08:28 EST 2005


> I add these lines to the header:
> MIME-Version: 1.0
> Content-Type: multipart/mixed; boundary="-d-i-v-i-d-i-n-g--l-i-n-e"

Maybe this will help, the send() method of my PHP MailMessage class:

  function send() {
    $this->write_debug_log("mail_mesg::send_mesg()");
    $boundary = 'PM'.chr(rand(65, 91)).'------'.md5(uniqid(rand()));
    if (strlen($this->destination) == 0) {
      $this->set_error(0, "Mail Message has no destination");
      return 0;
     }
    if (strlen($this->from) == 0) $this->from = $this->destination;
    if (strlen($this->reply_to) == 0) $this->reply_to = $this->from;
    $this->write_debug_log(sprintf("mail_mesg::send_mesg() - Message has
%d lines",
                             $this->get_count()));
    while ($counter < $this->get_count()) {
      $counter++;
      $this->set_position($counter);
      $body .= sprintf("%s\n", $this->get());
     }
    $email = "";
    $email  = "To: $this->destination".MIMECRLF;
    $email .= "From: $this->from".MIMECRLF;
    $email .= "Subject: " . $this->get_subject() . MIMECRLF;
    $email .= "X-Priority: 3".MIMECRLF;
    $email .= "X-Mailer: PHP/Apache/Linux".MIMECRLF;
    $email .= "Reply-To: $this->reply_to".MIMECRLF;
    $counter = 0;
    $body = "";
    while ($counter < $this->get_count()) {
      $counter++;
      $this->set_position($counter);
      $body .= sprintf("%s\n", $this->get());
     }

    if (sizeof($this->mimeparts) > 0) {
      $this->write_debug_log("mail_mesg::send_mesg() - This is a MIME
message");
      $email .= "MIME-Version: 1.0" . MIMECRLF;
      $email .= "Content-Type: multipart/mixed;" . MIMECRLF;
      $email .= "\tboundary=\"" . $boundary . "\"" . MIMECRLF;
      $email .= "Content-Transfer-Encoding: ".MIMEBIT7.MIMECRLF;
      $email .= MIMECRLF.MIMEWARNING.MIMECRLF.MIMECRLF ;
      if (!empty($body)) {
                $this->attach($body, MIMEBODY, MIMETEXT, MIMEBIT7,
"inline");
        }
      for ($i=0 ; $i < sizeof($this->mimeparts); $i++) {
        if ($this->debug_flag)
          $this->write_debug_log(sprintf("mail_mesg:send_mesg() -
Sending attachment %d", $i));
          if (!empty($this->mimeparts[$i]))
              $email .=
MIMECRLF.'--'.$boundary.MIMECRLF.$this->mimeparts[$i].MIMECRLF;
       }
      $email .= '--'.$boundary.'--'.MIMECRLF;
     } else {
        $this->write_debug_log("mail_mesg::send_mesg() - This is a
non-MIME message");
        $email .= MIMECRLF;
        $email .= "$body";
       }
    $this->write_debug_log("mail_mesg::send_mesg() - Summoning MDA");
    $fp = popen("/usr/sbin/sendmail -t", "w");
    if ($fp == 0) {
       $this->write_debug_log("mail_mesg::send_mesg() - Summon Failed");
       $this->set_error(0, "popen to send mail failed");
       $this->write_debug_log("popen to send mail failed");
       return 0;
      }
    $this->write_debug_log($email);
    fwrite($fp, $email);
    pclose($fp);
    return 1;
   }

It includes the MIME.def file that looks like -
<?php
        define('MIMEBASE64', 'base64');
        define('MIMEBIT7', '7bit');
        define('MIMEQP', 'quoted_printable');
        define('MIMEWARNING', 'This is a MIME encoded message');
        define('MIMEOCTET', 'application/octet-stream');
        define('MIMETEXT', 'text/plain');
        define('MIMEHTML', 'text/html');
        define('MIMEJPEG', 'image/jpg');
        define('MIMEGIF', 'image/gif');
        define('MIMEMSWORD', 'application/msword');
        define('MIMEPDF', 'application/pdf');
        define('MIMERTF', 'application/rtf');
        define('MIMETIFF', 'mage/tiff');
        define('MIMESTARWRITER', 'application/vnd.sun.xml.writer');
        define('MIMESTARIMPRESS', 'application/vnd.sun.xml.impress');
        define('MIMESTARDRAW', 'application/vnd.sun.xml.draw');
        define('MIMESTARCALC', 'application/vnd.sun.xml.calc');
        define('MIMEICS', 'text/calendar');
        define('MIMEVCARD', 'ext/x-vcard');
        define('MIMEMSEXCEL', 'application/vnd.ms-excel');
        define('MIMETTF', 'application/x-font-ttf');
        define('MIMEGNUMERIC', 'application/x-gnumeric');
        define('MIMECRLF', "\r\n");
        define('MIMECHARSET', 'us-ascii');
        define('MIMEINLINE', 'inline');
        define('MIMEATTACH', 'attachment');
        define('MIMEBODY', MIMECRLF.'BODY'.MIMECRLF);
?>

The attach method looks like -
function attach($data, $description = "", $contenttype = MIMEOCTET,
                 $encoding = MIMEBASE64, $disp = "attachment") {
  if ($this->debug_flag)
    $this->write_debug_log("mail_mesg:attach_file");
      if (empty($data)) {
              $this->write_debug_log("No data to be attached");
              return 0;
      }
    if (trim($contenttype) == '') $contenttype  = MIMEOCTET ;
    if (trim($encoding) == '') $encoding = MIMEBASE64;
    if ($encoding == MIMEBIT7) $emsg = $data;
      elseif ($encoding == MIMEQP)
              $emsg = $$this->qp_func($data);
      elseif ($encoding == MIMEBASE64) {
              if (!$this->base64_func)        # Check if there is
user-defined function
                      $emsg = base64_encode($data);
              else
                      $emsg = $$this->base64_func($data);
       }
    $emsg = chunk_split($emsg);
    //Check if content-type is text/plain and if charset is not
specified append default CHARSET
    if (preg_match("!^".MIMETEXT."!i", $contenttype) && !
preg_match("!;charset=!i", $contenttype))
            $contenttype .= ";\r\n\tcharset=".MIMECHARSET ;
    $msg = sprintf("Content-Type: %sContent-Transfer-Encoding: %s%s%s%
s",
             $contenttype.MIMECRLF,
             $encoding.MIMECRLF,
             ((($description) && (MIMEBODY != $description))?
               "Content-Description: $description".MIMECRLF:""),
             ($disp?"Content-Disposition: $disp".MIMECRLF:""),
MIMECRLF.$emsg.MIMECRLF);
    if (MIMEBODY==$description) {
      if ($this->debug_flag)
        $this->write_debug_log("mail_mesg:attach_file:attaching body");
        $this->mimeparts[0] = $msg;
       } else {
          if ($this->debug_flag)
            $this->write_debug_log("mail_mesg:attach_file:attaching
attachment");
            $this->mimeparts[sizeof($this->mimeparts) + 1] = $msg ;
              if ($this->debug_flag)
                $this->write_debug_log(
                  sprintf("mail_mesg:attach_file:size of mimeparts %d",
                  sizeof($this->mimeparts)));
          }
    return sizeof($this->mimeparts);
  }

Maybe that will help?

> And the body of the message looks like...
> --------------------------------------------
> You will only see this if you're using a non-MIME supporting Client!!
> -d-i-v-i-d-i-n-g--l-i-n-e
> Content-Type: text/html;
> <html>
>   <head>
>   ....
> </html>
> -d-i-v-i-d-i-n-g--l-i-n-e
> ----------------------------------------------
> More attachments work pretty much the same way. I have derived the above by
> inspecting a number of MIMEd mail messages as plain text files, and I'm omitting
> some detail
> Seems simple enough for EVERYONE'S favorite, HTML Mail! :)
> It is a simple example, and the main app generates HTML-based reports
> (PDF, when I get done with it).
> Anyway, I send the message, and it all looks well on recipt... UNTIL
> I try to read the attachment! This is why the above example is not more 
> complex; if It doesn't work, then I have missed something that would 
> probably be true for a more complex example, but something more complex
> would introduce other factors.... maybe...
> In any case, I get an amusing set of errors, the wording varies with the mail
> application I happen to be using....
> 
> Outlook 97:
>   
> An error prevented processing the message to completion. The original
> message is contained in the attached file MESSAGE.TXT
> 
> 	Which does NOT display as HTML.
> 
> mhstore: bogus multipart content in message xxxx
> 
> Really helpful...
> 
> I could try more clients, but I suspect I will only increase my collection
> of somewhat useless but mildly amusing error messages.
> I don't want to build something based on a pile of libraries, as I'm trying
> to keep this thing reasonably portable and compact. I am thinking that we 
> can build MIME'd  messages for special cases rather easily...
> I've also looked for more detailed information about all this, but found very
> little. Perhaps it is swamped by all the references to various MIME-capable
> applications...
> I lok forward to your replies...

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
Url : http://www.kalamazoolinux.org/pipermail/members/attachments/20051116/d69e4d07/attachment-0001.bin


More information about the Members mailing list