Skip to content

Send email with attachment with PHP mail()

2010 July 16
by Richard Knop

I am posting this function mainly for my own reference. I am making sure I can just copy and paste this function in the future without having to go through that silly headers mambo jumbo again. This function will correctly map a file extension to a mime type and send both plain text and html versions of email. Here it is:

  1. function sendEmailWithAttachment($toName, // recipient's name
  2.      $toEmail, // recipient's email
  3.      $fromName, // sender's name
  4.      $fromEmail, // sender's email
  5.      $emailText, // plain text email body
  6.      $emailHtml, // html email body
  7.      $fileToAttach /* path to a file you want to attach */)
  8. {
  9.  
  10.  $emailText = wordwrap($emailText, 70);
  11.  
  12.  $headers  = "To: $toName <$toEmail>\r\n";
  13.  $headers .= "From: $fromName <$fromEmail>\r\n";
  14.  
  15.  $random_hash = md5(date('r', time()));
  16.  $headers .= 'Content-Type: multipart/mixed; boundary="PHP-mixed-' . $random_hash . '"';
  17.  
  18.  $mimeTypes = array(
  19.   "323" => "text/h323",
  20.   "acx" => "application/internet-property-stream",
  21.   "ai" => "application/postscript",
  22.   "aif" => "audio/x-aiff",
  23.   "aifc" => "audio/x-aiff",
  24.   "aiff" => "audio/x-aiff",
  25.   "asf" => "video/x-ms-asf",
  26.   "asr" => "video/x-ms-asf",
  27.   "asx" => "video/x-ms-asf",
  28.   "au" => "audio/basic",
  29.   "avi" => "video/x-msvideo",
  30.   "axs" => "application/olescript",
  31.   "bas" => "text/plain",
  32.   "bcpio" => "application/x-bcpio",
  33.   "bin" => "application/octet-stream",
  34.   "bmp" => "image/bmp",
  35.   "c" => "text/plain",
  36.   "cat" => "application/vnd.ms-pkiseccat",
  37.   "cdf" => "application/x-cdf",
  38.   "cer" => "application/x-x509-ca-cert",
  39.   "class" => "application/octet-stream",
  40.   "clp" => "application/x-msclip",
  41.   "cmx" => "image/x-cmx",
  42.   "cod" => "image/cis-cod",
  43.   "cpio" => "application/x-cpio",
  44.   "crd" => "application/x-mscardfile",
  45.   "crl" => "application/pkix-crl",
  46.   "crt" => "application/x-x509-ca-cert",
  47.   "csh" => "application/x-csh",
  48.   "css" => "text/css",
  49.   "dcr" => "application/x-director",
  50.   "der" => "application/x-x509-ca-cert",
  51.   "dir" => "application/x-director",
  52.   "dll" => "application/x-msdownload",
  53.   "dms" => "application/octet-stream",
  54.   "doc" => "application/msword",
  55.   "dot" => "application/msword",
  56.   "dvi" => "application/x-dvi",
  57.   "dxr" => "application/x-director",
  58.   "eps" => "application/postscript",
  59.   "etx" => "text/x-setext",
  60.   "evy" => "application/envoy",
  61.   "exe" => "application/octet-stream",
  62.   "fif" => "application/fractals",
  63.   "flr" => "x-world/x-vrml",
  64.   "gif" => "image/gif",
  65.   "gtar" => "application/x-gtar",
  66.   "gz" => "application/x-gzip",
  67.   "h" => "text/plain",
  68.   "hdf" => "application/x-hdf",
  69.   "hlp" => "application/winhlp",
  70.   "hqx" => "application/mac-binhex40",
  71.   "hta" => "application/hta",
  72.   "htc" => "text/x-component",
  73.   "htm" => "text/html",
  74.   "html" => "text/html",
  75.   "htt" => "text/webviewhtml",
  76.   "ico" => "image/x-icon",
  77.   "ief" => "image/ief",
  78.   "iii" => "application/x-iphone",
  79.   "ins" => "application/x-internet-signup",
  80.   "isp" => "application/x-internet-signup",
  81.   "jfif" => "image/pipeg",
  82.   "jpe" => "image/jpeg",
  83.   "jpeg" => "image/jpeg",
  84.   "jpg" => "image/jpeg",
  85.   "js" => "application/x-javascript",
  86.   "latex" => "application/x-latex",
  87.   "lha" => "application/octet-stream",
  88.   "lsf" => "video/x-la-asf",
  89.   "lsx" => "video/x-la-asf",
  90.   "lzh" => "application/octet-stream",
  91.   "m13" => "application/x-msmediaview",
  92.   "m14" => "application/x-msmediaview",
  93.   "m3u" => "audio/x-mpegurl",
  94.   "man" => "application/x-troff-man",
  95.   "mdb" => "application/x-msaccess",
  96.   "me" => "application/x-troff-me",
  97.   "mht" => "message/rfc822",
  98.   "mhtml" => "message/rfc822",
  99.   "mid" => "audio/mid",
  100.   "mny" => "application/x-msmoney",
  101.   "mov" => "video/quicktime",
  102.   "movie" => "video/x-sgi-movie",
  103.   "mp2" => "video/mpeg",
  104.   "mp3" => "audio/mpeg",
  105.   "mpa" => "video/mpeg",
  106.   "mpe" => "video/mpeg",
  107.   "mpeg" => "video/mpeg",
  108.   "mpg" => "video/mpeg",
  109.   "mpp" => "application/vnd.ms-project",
  110.   "mpv2" => "video/mpeg",
  111.   "ms" => "application/x-troff-ms",
  112.   "mvb" => "application/x-msmediaview",
  113.   "nws" => "message/rfc822",
  114.   "oda" => "application/oda",
  115.   "p10" => "application/pkcs10",
  116.   "p12" => "application/x-pkcs12",
  117.   "p7b" => "application/x-pkcs7-certificates",
  118.   "p7c" => "application/x-pkcs7-mime",
  119.   "p7m" => "application/x-pkcs7-mime",
  120.   "p7r" => "application/x-pkcs7-certreqresp",
  121.   "p7s" => "application/x-pkcs7-signature",
  122.   "pbm" => "image/x-portable-bitmap",
  123.   "pdf" => "application/pdf",
  124.   "pfx" => "application/x-pkcs12",
  125.   "pgm" => "image/x-portable-graymap",
  126.   "pko" => "application/ynd.ms-pkipko",
  127.   "pma" => "application/x-perfmon",
  128.   "pmc" => "application/x-perfmon",
  129.   "pml" => "application/x-perfmon",
  130.   "pmr" => "application/x-perfmon",
  131.   "pmw" => "application/x-perfmon",
  132.   "pnm" => "image/x-portable-anymap",
  133.   "pot" => "application/vnd.ms-powerpoint",
  134.   "ppm" => "image/x-portable-pixmap",
  135.   "pps" => "application/vnd.ms-powerpoint",
  136.   "ppt" => "application/vnd.ms-powerpoint",
  137.   "prf" => "application/pics-rules",
  138.   "ps" => "application/postscript",
  139.   "pub" => "application/x-mspublisher",
  140.   "qt" => "video/quicktime",
  141.   "ra" => "audio/x-pn-realaudio",
  142.   "ram" => "audio/x-pn-realaudio",
  143.   "ras" => "image/x-cmu-raster",
  144.   "rgb" => "image/x-rgb",
  145.   "rmi" => "audio/mid",
  146.   "roff" => "application/x-troff",
  147.   "rtf" => "application/rtf",
  148.   "rtx" => "text/richtext",
  149.   "scd" => "application/x-msschedule",
  150.   "sct" => "text/scriptlet",
  151.   "setpay" => "application/set-payment-initiation",
  152.   "setreg" => "application/set-registration-initiation",
  153.   "sh" => "application/x-sh",
  154.   "shar" => "application/x-shar",
  155.   "sit" => "application/x-stuffit",
  156.   "snd" => "audio/basic",
  157.   "spc" => "application/x-pkcs7-certificates",
  158.   "spl" => "application/futuresplash",
  159.   "src" => "application/x-wais-source",
  160.   "sst" => "application/vnd.ms-pkicertstore",
  161.   "stl" => "application/vnd.ms-pkistl",
  162.   "stm" => "text/html",
  163.   "svg" => "image/svg+xml",
  164.   "sv4cpio" => "application/x-sv4cpio",
  165.   "sv4crc" => "application/x-sv4crc",
  166.   "t" => "application/x-troff",
  167.   "tar" => "application/x-tar",
  168.   "tcl" => "application/x-tcl",
  169.   "tex" => "application/x-tex",
  170.   "texi" => "application/x-texinfo",
  171.   "texinfo" => "application/x-texinfo",
  172.   "tgz" => "application/x-compressed",
  173.   "tif" => "image/tiff",
  174.   "tiff" => "image/tiff",
  175.   "tr" => "application/x-troff",
  176.   "trm" => "application/x-msterminal",
  177.   "tsv" => "text/tab-separated-values",
  178.   "txt" => "text/plain",
  179.   "uls" => "text/iuls",
  180.   "ustar" => "application/x-ustar",
  181.   "vcf" => "text/x-vcard",
  182.   "vrml" => "x-world/x-vrml",
  183.   "wav" => "audio/x-wav",
  184.   "wcm" => "application/vnd.ms-works",
  185.   "wdb" => "application/vnd.ms-works",
  186.   "wks" => "application/vnd.ms-works",
  187.   "wmf" => "application/x-msmetafile",
  188.   "wps" => "application/vnd.ms-works",
  189.   "wri" => "application/x-mswrite",
  190.   "wrl" => "x-world/x-vrml",
  191.   "wrz" => "x-world/x-vrml",
  192.   "xaf" => "x-world/x-vrml",
  193.   "xbm" => "image/x-xbitmap",
  194.   "xla" => "application/vnd.ms-excel",
  195.   "xlc" => "application/vnd.ms-excel",
  196.   "xlm" => "application/vnd.ms-excel",
  197.   "xls" => "application/vnd.ms-excel",
  198.   "xlt" => "application/vnd.ms-excel",
  199.   "xlw" => "application/vnd.ms-excel",
  200.   "xof" => "x-world/x-vrml",
  201.   "xpm" => "image/x-xpixmap",
  202.   "xwd" => "image/x-xwindowdump",
  203.   "z" => "application/x-compress",
  204.   "zip" => "application/zip"
  205.  );
  206.  
  207.  $extension = end(explode('.', $fileToAttach));
  208.  $mimeType = $mimeTypes[$extension];
  209.  $fileName = end(explode('/', $fileToAttach));
  210.  
  211.  $attachment = chunk_split(base64_encode(file_get_contents($fileToAttach)));
  212.  
  213. $output = "
  214. –PHP-mixed-$random_hash;
  215. Content-Type: multipart/alternative; boundary='PHP-alt-$random_hash'
  216. –PHP-alt-$random_hash
  217. Content-Type: text/plain; charset='iso-8859-1'
  218. Content-Transfer-Encoding: 7bit
  219.  
  220. $emailText
  221.  
  222. –PHP-alt-$random_hash
  223. Content-Type: text/html; charset='iso-8859-1'
  224. Content-Transfer-Encoding: 7bit
  225.  
  226. $emailHtml
  227.  
  228. –PHP-alt-$random_hash–
  229.  
  230. –PHP-mixed-$random_hash
  231. Content-Type: application/$mimeType; name=$fileName
  232. Content-Transfer-Encoding: base64
  233. Content-Disposition: attachment
  234.  
  235. $attachment
  236. –PHP-mixed-$random_hash–";
  237.  
  238.  mail($toEmail, $subject, $output, $headers);
  239.  
  240. }

Hope somebody will find it useful.

2 Responses leave one →
  1. Jonny permalink
    July 1, 2011

    A very useful reference. However, boundaries should begin with two hyphens and end with 2 according to the mime rfc1341, the example above would not work without issues in e.g. gmail. I learned this the hard way by taking your code as a start point for my script where it simply put everything in the message body as text before fixing it.

  2. Jonny permalink
    July 1, 2011

    Also filename should be in the content-disposition header, and you have redundant (invalid) “application/” in the content-type. You forgot the $subject parameter in the function construct but I guess you posted this code in a slight hurry, so I won’t critisize, it was overall very helpful as a rough reference to build on.

    In regards to the hyphens comment, it may be I had soft ones corrupting my script, though I still prefer using proper ones.

Leave a Reply

Note: You can use basic XHTML in your comments. Your email address will never be published.

Subscribe to this comment feed via RSS