Zend Certified Engineer

phpguru.org

Free PHP, Javascript and C# code

HTML Mime Mail 5

It's upgradin' time! With the advent of PHP5 cometh a whole new era of rewriting old classes to make use of the new object system. Perhaps in many cases, for no great reason other than to make use of the new object system.
Fun though.

So, in true "pointless upgrade" style, I've upgraded the ever popular HTML Mime Mail class to use the PHP5 object system. Yes, it's a bit of a pants name, but such is life. This article is going to document the new version, now called, htmlMimeMail5. Cute huh?

Not much has changed; the properties and methods make use of the private/public access modifiers, embedded images and attachments are handled slightly differently, and the class now supports setting mail priorities. The class also now always sets a text part to the email, whether there's any text or not.

So off we go down the yellow brick road. Get ready Oz.

<?php
    
require_once("htmlMimeMail5.php");
    
    
$mail = new htmlMimeMail5();
?>

Not much different here. Include the file using require_once(), and create a new instance of the class. You should note that all the .php files in the zip file should be held in the same directory. The code will handle dragging them in at the appropriate time.

<?php
    $mail
->setFrom("Richard <richard@example.com>");
?>

Sets the From: address of the email. The method can accept email addresses of the above format (friendly name portion and address), and also just addresses.

<?php
    $mail
->setSubject('Test email');
?>

Sets the subject of the email. Pretty straight forward.

<?php
    $mail
->setPriority('high');
?>

Sets the priority of the email. Acceptable arguments are "high", "normal" or "low". It can also accept either 1, 3 or 5, which correspond respectively with the former.

<?php
    $mail
->setText('Sample text');
?>

Sets the text part of the email.

<?php
    $mail
->setHTML('<body background="background.gif"><b>Sample HTML</b></body>');
?>

Sets the HTML part of the email. Naturally this is totally optional, if you don't want to send an HTML email, don't set any HTML. Here, there is a background attribute on the body tag. This can contain an absolute path to an image held on the internet, or as we're going to do here, a filename of an image file which will be embedded into the email. This makes the email larger, but increases greatly the potential of the end user seeing the image(s).

<?php
    $mail
->addEmbeddedImage(new fileEmbeddedImage('background.gif', 'image/gif', new Base64Encoding()));
?>

This is the first significant difference from previous versions of the class. This method used to be called addHTMLImage(), howeever I thought this was better. Has a nicer ring to it too. And then there's the argument. Previously it took three arguments, however now it takes just the one, which would be fileEmbeddedImage object, or a stringEmbeddedImage object. These objects in turn handle either loading the image from disk, or taking it from a variable. The fileEmbeddedImage object as you can see takes three arguments, being the filename, the content type and an encoding type. The encoding type should also be an object, either a Base64Encoding object, or a QPrintEncoding object. The latter should rarely be used. In fact, the last two arguments of the fileEmbeddedImage object are optional, defaulting to "application/octet-stream" and base64 encoding. The stringEmbeddedImage differs in that it takes the image data as the first argument instead of a filename. The second argument is the name to use as the file name of the image (this is taken from the filename with the fileEmbeddedImage object). The third and fourth arguments are the content type and encoding type, as with the fileEmbeddedImage object.

<?php
    $mail
->addAttachment(new fileAttachment('example.zip', 'application/zip', new Base64Encoding()));
?>

This is the second significant difference from prior versions. This method has been changed to work in the same way as addEmbeddedImage(), in that it now takes a single argument instead of three. The objects that should be used however, are named slightly differently, being fileAttachment for a file on disk, and stringAttachment for a file which you have loaded into a variable. These objects take the same objects to their constructors as the embedded image objects.

<?php
    $mail
->send(array('richard@example.com'));
?>

Hurrah. Now we send the email. The send() method takes two arguments, the first being an array of recipients ( again, the email addresses can be specified with or without the friendly name part), and the optional second being the method of sending to use. This defaults to "mail", which uses the built in PHP mail() function, or it can also be "sendmail" or "smtp". If using either "sendmail" or "smtp", you should check the reference for methods which change either the sendmail path, or SMTP parameters.

That's it. We have reached the mighty city of Oz. Time to disembark until next time. Last thing is the method reference, which lists all available public methods, and what they do.

Ciao.

Method Reference

Method Description
Constructor Doesn't take any arguments. Not much to say I guess.
setCRLF(string $crlf) Sets the CRLF line ending type to use. You should not use this unless you're sure you know what you're doing, as the code will correctly (most of the time) determine which type to use by itself.
setSMTPParams(string $host,
int $port,
string $helo,
bool $auth,
string $user,
string $pass)
Set SMTP parameters when using SMTP to send the email. All optional, though not specifying any would be pointless... Pretty self explanatory really - hostname to connect to, port to connect to, text to send as part of the HELO command, whether to use SMTP authentication, and if so the username and password to use.
setSendmailPath(string $path) Sets the path to use when using sendmail method of sending the email. This should be the full path to the sendmail binary on your system, along with any command line parameters. Defaults to "/usr/lib/sendmail -ti".
setTextEncoding(object $encoding) Sets the encoding to use (if any) on the plain text part of the email. The argument should be one of the encoding objects, ie Base64Encoding, QPrintEncoding, SevenBitEncoding or EightBitEncoding. Bit pants about the 7bit/8bit names, but identifiers in PHP can't start with a number. Tits.
setHTMLEncoding(object $encoding) Sets the encoding to use (if any) on the HTML part of the email. The argument should be one of the encoding objects, ie Base64Encoding, QPrintEncoding, SevenBitEncoding or EightBitEncoding.
setTextCharset(string $charset) Sets the characterset to use on the plain text portion of the email. Defaults to "ISO-8859-1".
setHTMLCharset(string $charset) Sets the characterset to use on the plain text portion of the email. Defaults to "ISO-8859-1".
setHeadCharset(string $charset) Sets the characterset to use on the headers of the email. Defaults to "ISO-8859-1".
setTextWrap(int $count) Set the point at which text is wrapped in the email. Defaults to 998, which is a limit imposed by the SMTP standard.
setHeader(string $name, string $value) Sets a header of the email. First argument if the name of the email, second is the value.
setSubject(string $subject) Sets the subject of the email.
setFrom(string $from) Sets the From: header of the email.
setPriority(mixed $priority) Sets the priority of the email. Defaults to "normal". Argument can be either "high", "normal" or "low", or 1, 3 or 5 respectively.
setReturnPath(string $return_path) Sets the Return-Path: of the email. This is the address to which bounces will be sent if the email fails to be delivered.
setCc(string $cc) Sets the Cc: header of the email. The email will be delivered to these addresses as well as those specified in the send() method.
setBcc(string $bcc) Sets the Bcc: header of the email. The email will be delivered to these addresses as well as those specified in the send() method. However, the Bcc: header will be removed from email before it is sent, so those addresses in the To: and Cc: headers will not know it has also been sent to these addresses. Hence, "Blind" Carbon Copy.
setText(string $text) Sets the text part of the email.
setHTML(string $html[, string $images_dir]) Sets the HTML part of the email. The optional second argument specifies a directory where the code should look for images referenced by the HTML. If found, these images will automatically be embedded into the email.
addEmbeddedImage(object $embeddedImage) Adds an embeddded image to the email. The argument should be on of the fileEmbeddedImage or stringEmbeddedImage objects, depending on the source of the image.
addAttachment(object $attachment) Adds an attachment to the email. The argument should be one of the fileAttachment or stringAttachment objects, depending on the source of the attachment.
send(array $recipients[, string $type]) Sends the email. The first argument is an array of recipients to whom the email will be sent to. The second is how to send the email. This can be one of "mail", "sendmail" or "smtp", and defaults to "mail".
getRFC822(array $recipients[, string $type]) This function first of all builds the email, and then returns it in text format. This is useful if you need to attach the email to another email. This could be done like so: $mail_2->addAttachment(new stringAttachment($mail_1->getRFC822(array('richard@example.com')), 'message/rfc822')) The first argument is an array of recipients to place in the To: header, whilst the second, optional, $type argument should be the same as that you intend to use eventually for the send() method. This is to ensure the correct line endings are used.
RSS Feed for Comments

Comments

Author: nlared
Posted: 25th January 2005 23:11
all the functions are for encode but what about decode?
Author: Richard Heyes
Posted: 26th January 2005 18:18
This class doesn't handle decoding of email. Try the Mail category at http://pear.php.net/
Author: Ally
Posted: 28th January 2005 19:46
Does it still work with PHP4?
If not, do you offer PHP4's version?
Thanks.
Author: Richard Heyes
Posted: 29th January 2005 22:03
No. This upgrade naturally only works with PHP5, as it uses PHP5 features. The older version for PHP4 is available in the download area.
Author: Andy
Posted: 2nd February 2005 19:12
Hi Richard,

I downloaded the phpMimeMail API (both).
I realized that the function
_findHtmlImages / findHtmlImages
of your class doesn't support background-images declared with CSS, so I modified the regular expression.

In case you want to use it, feel free:

v2.5.1:
preg_match_all('/(?:"|\'|.*\()([^"\']+\.('.implode('|',
$extensions).'))(?:"|\'|\))/Ui', $this->html, $images);

MimeMail5:
preg_match_all('/(?:"|\'|.*\()([^"\']+\.('.implode('|',
$extensions).'))(?:"|\'|\))/Ui', $this->html, $matches);


It it definitely not the best way to handle this ('.*'), but the only way I found. Hopefully it's reusable ;)
Author: Rosko
Posted: 17th February 2005 11:46
in _findHtmlImages, if there is a special symbol in the image path which is URLEncoded, the image won't be found by file_exists() and therefore will not be embedded in the message.
Take a look at this example:
<img src="/image%20with%20intervals.jpg">
the real path on the filesystem is:
"images_dir/image with intervals.jpg"

calling file_exists("images_dir/image%20with%20intervals.jpg") returns FALSE and we just missed the image... :(
Author: Sigge
Posted: 17th February 2005 21:36
Question:

When sending through sendmail or smtp - does it connect to the server once per mail, or once per session?

I need something that cand send approx 1000 emails without bogging down the server. Is this for me?
Author: Richard Heyes
Posted: 18th February 2005 01:51
Sigge:
> Question:
>
> When sending through sendmail or smtp - does it
> connect to the server once per mail, or once per
> session?

When sending via sendmail a new sendmail process will be spawned for each mail, and likewise via SMTP one new connection will be generated for each mail.

> I need something that cand send approx 1000
> emails without bogging down the server. Is this
> for me?

Not without some modification.
Author: Sigge
Posted: 20th February 2005 20:09
Richard Heyes:
> Sigge:

> > I need something that cand send approx 1000
> > emails without bogging down the server. Is
> this
> > for me?
>
> Not without some modification.
I'm not very familiar with the smtp protocol, but do you know if it's a lot of modification, or just changing the loop in question to only connect once?
Will take a look at the code perhaps...

Sigge
Author: Desty Nova
Posted: 23rd February 2005 17:20
Richard Heyes:
> No. This upgrade naturally only works with PHP5,
> as it uses PHP5 features. The older version for
> PHP4 is available in the download area.

I can't find the PHP4 version in your download area. Can you help ?

Author: John Lange
Posted: 24th February 2005 06:16
Richard, what is the license for this project? htmlMimeMail.php indicates it is copyright yourself which implies all rights reserved. But then again, it also says it was last updated in 2002!

And I don't see any indication of a license mentioned on this site.

If you could email me with license clarification that would be greatly appreciated.

john.lange (at) open-it.ca

I tried to email you directly using the address in mimePart.php (richard@phpguru.org) but that bounces.
Author: Richard Heyes
Posted: 24th February 2005 12:52
John Lange:
> Richard, what is the license for this project?
> htmlMimeMail.php indicates it is copyright
> yourself which implies all rights reserved. But
> then again, it also says it was last updated in
> 2002!
>
> And I don't see any indication of a license
> mentioned on this site.
>

Consider the old version BSD license.

> I tried to email you directly using the address
> in mimePart.php (richard@phpguru.org) but that
> bounces.

Yup, that's not my email address. :-)
Author: Ramon
Posted: 25th February 2005 22:37
Hi Richard,

First I must say that this mailing thing is really nice and this one actually works(thousands of other ones doesn't come up right).

But I'v one problem. Now I'm trying to sent a html mail with some text in it. I use the example 2 form your older download package. The mail is arriving okay, I see the html. But the problem here is that the text (form e.g. example.txt, or from text ebedded in the variable $text) will just not show up. Can you please help me and tell me what the problem here is, and tell me a solutions.

tnx
sinc.
Ramon
(Netherlands)
Author: James Benson
Posted: 28th February 2005 15:12
When it says in the description above about the 'array of recipients' to send to does this mean its possible to send the same email at the same time through the same script to different people?
I've looked at the array section of the php man, tried adding multiple addresses to the 'to' field but never had more than one email without creating a new script object for each of the emails i need to send, is this possible and what format array should i use to do this?

MimeMail is a miracle, Richard you deserve an award, very easy to use, thanks.
Author: Richard Heyes
Posted: 28th February 2005 15:18
James Benson:
> When it says in the description above about the
> 'array of recipients' to send to does this mean
> its possible to send the same email at the same
> time through the same script to different
> people?
> I've looked at the array section of the php
> man, tried adding multiple addresses to the
> 'to' field but never had more than one email
> without creating a new script object for each
> of the emails i need to send, is this possible
> and what format array should i use to do this?

Simple:

$mimeObj->send(array('joe@example.com', 'bloggs@example.com'));

Bear in mind that if you're trying to send two to yourself, your mail server might be filtering the duplicates out. Cyrus IMAP server used to do this by default, not sure if it still does.

> MimeMail is a miracle, Richard you deserve an
> award, very easy to use, thanks.

Ta very much.
Author: Richard
Posted: 1st March 2005 10:56
Are the 'comprehensive useage examples' mentioned on zend.com for the php 4 version of your Mime Mail available anywhere please?
Author: Richard Heyes
Posted: 1st March 2005 17:01
If you extract the .tar.gz file, you will magically find five (5!) example scripts.
Author: Dan
Posted: 3rd March 2005 12:33
Hello,

I am trying to locate the HTML MIME Mail class for PhP 4 but I can't seem to find it. The PhP 4 link on this site points to the PhP5 info and the download directory just lists the PhP 5 files.

Is the PhP4 version still available?

Dan
Author: Richard Heyes
Posted: 3rd March 2005 14:20
Dan:
> Hello,
>
> I am trying to locate the HTML MIME Mail class
> for PhP 4 but I can't seem to find it. The PhP
> 4 link on this site points to the PhP5 info and
> the download directory just lists the PhP 5
> files.

<sigh> The HTML Mime Mail page has two headings, "Latest Version", which details the PHP5 version, and "Prior Version" which, believe it or not, details the PHP4 version. The PHP4 version has a version number of 2.5.1, which you will find in the download area, where it has been for well over a year now.

Enjoy.
Author: Lars B. Jensen
Posted: 7th March 2005 06:17
Humm, trying to send out Japanese mails, and somehow it seems the encodeHeader doesnt always catch on to me sending out with different encoding. For the record, I am using the newest package for PHP5

The way I read the code and comments, if I pass the iso-2022-jp encoding as parameter to my converted string, but it doesnt work - it comes out scrambled. Tweaking it a bit, I can make it work in OE, but being so forgiving as it is, it's not really a good test scenario.

To make it work in eg. Opera mailer, which is more strict on headers and encoding, I have to encode my subject using like

$subject = "=?".$charset."?B?".base64_encode(mb_convert_encoding(mb_convert_kana('&#20225;&#26989;&#12434;&#21839;&#12431;&#12378;', "KV"), "JIS"))."?=";
$mail->setSubject($subject);

rather than

$subject = mb_convert_encoding(mb_convert_kana('&#20225;&#26989;&#12434;&#21839;&#12431;&#12378;', "KV"), "JIS");
$mail->setSubject($subject);

Which I supposed would work better. I did some light debugging but didnt nail down where it fail. I am willing to assist with debugging if nessary.

I did set the header encoding to iso-2022-jp and the rest of the mail works fine, it's the subject which is the teaser

Thanks for a cool script though,

/ Lars
lars.jensen@careercross.com
Author: Michal Borychowski
Posted: 16th March 2005 08:31
I live in Poland where we use ISO-8859-2, so I quickly noticed that the function encodeHeader() doesn't work correctly.

It breaks when in a header string there are more than one [\x80-\xFF] string chains. Let us call it BADSTRING. So the function breaks at string: "Some text BADSTRING, and here another BADSTRING". Breaking means it erroneously uses twice "=?ISO-8859-2?Q?="

Moreover, I think this funcion should change spaces to underscores, underscores to =5F, and of course, eqal signs to =3D.


Here are two strings after encoding. One encoded with original function:

Test sign: =?ISO-8859-2?Q?=F3?=; underscore: _; equal sign: =; some other letters; other test sign: =?ISO-8859-2?Q?=F3?=

and the one encoded after my modifications:

=?ISO-8859-2?Q?Test_sign:_=F3;_underscore:_=5F;_equal_sign:_=3D;_some_other_letters;_other_test_sign:_=F3?=


I believe the second is the proper one. I changed the function this way:

if (preg_match("/[-\x1f\x80-\xff]/", $input)) {
$replacement = preg_replace('/([\x00-\x1f\x80-\xFF_=])/e', '"=" . strtoupper(dechex(ord("\1")))', $input);
$replacement = str_replace(' ', '_', $replacement);
$input = '=?' . $charset . '?Q?' . $replacement . '?=';
}
return $input;


I hope it helps!

Regards
Michal


Author: Ben D
Posted: 9th April 2005 18:09
Currently using the php4 version, and works great except to, what appears to be, Lotus mail client where embedded images appear at end of email and several characters are converted to japanese characters (although I think this is the person's browser interpreting windows curly quotes - not sure).

Has anyone had success in emailing an html mail with embedded attachments to Lotus successfully? and do I need to update to php5 and your latest version?

Richard: Nice code, happy to help on your wishlist if you can help with advice/updates.

Author: MindFly
Posted: 27th April 2005 19:33
I have two mail accounts, i recieves the whole mime mail with inline images etc. the other revieves this:

Content-Type: text/plain; charset="ISO-8859-1"

Content-Transfer-Encoding: 7bit

Can someone help me out?
Author: Jimbo
Posted: 28th April 2005 23:36
Hello:
I already test this method to just one user.
The problem is when I tried to send many Bcc copies.

setBcc(string $bcc)

The problem is that just the first mail I used in Bcc form is deliveried and the rest are not.

Do u have any clue to send all the user I am trying to reach?

Here it is the example I`m using.
$mail->setFrom("Richard <richard@example.com>");
$mail->setBcc("dir1@example1.net dir2@example2.net");
$mail->setSubject('Test email');
$mail->setText('Sample text');
$mail->send(array('richard@example.com'));


Thanks

Jaime
Author: michel
Posted: 29th April 2005 00:21
this class is good. but it doesn't work when sending mails that have text par and htlm part.

And the author don't accept to gice any help.

I'll try another mail class that work.
Author: Keiron
Posted: 6th May 2005 10:54
How do you embed a flash file? I have added it to the htmll page and it will come through as an attachment not embedded!
Author: Andrew
Posted: 24th May 2005 11:01
dear Richard,

it would be indeed very helpful, as well as appreciated by many users worldwide, if you had invested your time into support for PHP 4!!! i tried to convert htmlMimeMail5 and related classes myself to support PHP 4 syntax, and i did something wrong, so the mail isn't built correctly when i build a multi-part mail with embedded images. i persoanally gave up, and the biggest problem for me is that htmkMimeMail 2.5.1 does not support multi-part mail with inline attachments for our commercial Microsoft Outlook clients..... i thought maybe you'll be interested to check it out.

best wishes,

andrew.
Author: Daniel Watrous
Posted: 25th May 2005 23:18
You mentioned in a previous post that the original htmlMimeMail was offered under a BSD license. I am writing a closed source application and don't anticipate any modifications to your class, though I would like to use it. The current download contains the GPL license. Do you offer a version that is friendly to a closed source project? LGPL or PHP for example?
Author: Richard Quadling
Posted: 27th May 2005 09:49
In the htmlMineMail5.php script, would it not be better to use ...

$this->smtp_params['host'] = ini_get('SMTP');
$this->smtp_params['port'] = ini_get('smtp_port');

rather than hard-coding them?

This way, the sysop controls the setup.

Regards,

Richard Quadling.
Author: Richard Heyes
Posted: 28th May 2005 20:36
Richard Quadling:
> In the htmlMineMail5.php script, would it not be
> better to use ...
>
> $this->smtp_params['host'] = ini_get('SMTP');
> $this->smtp_params['port'] =
> ini_get('smtp_port');
>
> rather than hard-coding them?
>
> This way, the sysop controls the setup.

Nope.
Author: Richard Quadling
Posted: 1st June 2005 14:05
Hi.

I just realised what I said and now I agree.

Instead, I use the normal mail method and set the "from" address via ...

ini_set('sendmail_from', 'xxxx@yyy.com');

This way, each script which sends email can decide who it is that is sending the email!

Excellent script by the way!

Richard.
Author: Richard Heyes
Posted: 1st June 2005 14:10
Richard Quadling:
> Hi.
>
> I just realised what I said and now I agree.
>
> Instead, I use the normal mail method and set
> the "from" address via ...
>
> ini_set('sendmail_from', 'xxxx@yyy.com');
>
> This way, each script which sends email can
> decide who it is that is sending the email!

Well you can do that anyway with the headers argument - mail('...', '...', '...', 'From: foo@bar.com')

> Excellent script by the way!

Thanks!
Author: yuri
Posted: 2nd June 2005 10:43
really i can't find php4 version of this spcript... nowhere, maybe i need glasses :(

can u put the URL for download this script?

THANX A LOT!

Post Comment

Your name:
Your email: (Don't worry, I won't spam your ass.)
Comments:
  Do not post support type questions please

  To prevent spamming "mofos", enter the following number numerically in the following text input. Eg. For "two hundred and two", you would enter "202" (no quotes).
  eight thousand seven hundred and fifteen
Number: