{
    "href": "/post/2007/07/18/sending-mail-with-solar/",
    "relId": "2007/07/18/sending-mail-with-solar",
    "title": "Sending Mail with Solar",
    "author": "pmjones",
    "markup": "html",
    "tags": [
        {
            "href": "/tag/php/",
            "relId": "php",
            "title": "PHP",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/solar/",
            "relId": "solar",
            "title": "Solar",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        }
    ],
    "created": "2007-07-18 13:00:18 UTC",
    "updated": [
        "2007-07-18 13:00:18 UTC"
    ],
    "html": "<p>Ah, sending mail, the bane of everyone who has ever used the php <a href=\"http://php.net/mail\">mail()</a> function for anything remotely non-trivial.  There are lots of entries in the \u201chelps you send mail\u201d category in PHP userland:</p>\n<ul>\n<li><a href=\"http://pear.php.net/package/Mail\">PEAR Mail</a></li>\n<li><a href=\"http://phpmailer.sourceforge.net/\">PhpMailer</a></li>\n<li><a href=\"http://www.swiftmailer.org/\">SwiftMailer</a></li>\n<li><a href=\"http://framework.zend.com/manual/en/zend.mail.html\">Zend_Mail</a></li>\n</ul>\n<p>While each of these will work with <a href=\"http://solarphp.com\">Solar</a>, the new <a href=\"http://solarphp.com/package/Solar_Mail\"><code>Solar_Mail</code></a> and <a href=\"http://solarphp.com/package/Solar_Smtp\"><code>Solar_Smtp</code></a> packages work \u201cnatively\u201d, in that they support automatic configuration, locale and exception inheritance, and so on.  Read on for some examples on how to use them.</p>\n<p><!--more--></p>\n<h3>A Basic Mail Message</h3>\n<p>Here\u2019s a short example on how to build a basic message and set the recipients. In this example, I\u2019ll send a quick note to my old friend Bolivar Shagnasty, and give him both a text and HTML version of the message.</p>\n<p>Note that the <code>Solar_Mail_Message</code> set*() methods are fluent, so you can chain them together when you find it appropriate.  (You can review the full set of <a href=\"http://solarphp.com/class/Solar_Mail_Message\"><code>Solar_Mail_Message</code> methods</a> if you like.)</p>\n<pre><code>$text = &lt;&lt;&lt;TEXT\nThe quick brown fox jumps over the lazy dog.\n\nNow is the time for all good men to come to the aid of their country.\nTEXT;\n\n$html = &lt;&lt;&lt;HTML\n&lt;p&gt;The quick brown fox jumps &lt;em&gt;over&lt;/em&gt; the lazy dog.&lt;/p&gt;\n\n&lt;p&gt;&lt;strong&gt;Now&lt;/strong&gt; is the time for all good men\nto come to the aid of their country.&lt;/p&gt;\nHTML;\n\n$mail = Solar::factory('Solar_Mail_Message');\n\n$mail-&gt;setCharset('utf-8')\n     -&gt;setFrom('pmjones@example.com', 'Paul M. Jones')\n     -&gt;addTo('boshag@example.com', 'Bolivar Shagnasty')\n     -&gt;addCc('nobody@example.net')\n     -&gt;setSubject('A Short Test Message')\n     -&gt;setText($text)\n     -&gt;setHtml($html);\n</code></pre>\n<p>That\u2019s pretty easy \u2026 but is it safe?</p>\n<h3>Headers and Header Injection</h3>\n<p>Anything that ends up getting sent as a mail header, including addresses and the subject line, is sanitized against header-injection attacks by removing newlines from the header label and value.  Let\u2019s say you want to add a new custom header:</p>\n<pre><code>$mail = Solar::factory('Solar_Mail_Message');\n$mail-&gt;setHeader('X-Custom-Header', \"FoornrnAn evil message\");\n</code></pre>\n<p>Under a less-secure system this might cause the header to be sent as:</p>\n<pre><code>X-Custom-Header: Foo\n\nAn evil message.\n</code></pre>\n<p>That\u2019s no good \u2013 somebody just injected their own message into our email.</p>\n<p>With <code>Solar_Mail_Message</code>, when the mail gets sent, that header will go out as:</p>\n<pre><code>X-Custom-Header: FooAn evil message\n</code></pre>\n<p>We strip the newlines in header labels and values automatically, so you should be safe against header injections.  (If there are other aspects to securing against header injections I would be happy to hear them.)</p>\n<h3>Attachments</h3>\n<p>Adding an attachment to an email is pretty easy; you can use a convenience method to attach a file, or you can build it yourself.</p>\n<p>Convenience method <code>attachFile()</code>:</p>\n<pre><code>$file_path = '/path/to/file.pdf';\n$mime_type = 'application/pdf';\n\n// this will automatically set the attachment name\n// to the basename() of the attached file\n$mail = Solar::factory('Solar_Mail_Message');\n$mail-&gt;attachFile($file_name, $mime_type);\n</code></pre>\n<p>Or you can build and add a MIME part yourself with <code>attachPart()</code>:</p>\n<pre><code>$file_path = '/path/to/file.pdf';\n$mime_type = 'application/pdf';\n\n$part = Solar::factory('Solar_Mail_Message_Part');\n$part-&gt;setDisposition('attachment');\n$part-&gt;setFilename(basename($file_name));\n$part-&gt;setContent(file_get_contents($file_name));\n$part-&gt;setType($mime_type);\n\n$mail = Solar::factory('Solar_Mail_Message');\n$mail-&gt;attachPart($part);\n</code></pre>\n<h3>Sending The Message</h3>\n<p>Now that we have a message to send, let\u2019s actually get it out there.  To send the message, we need to pick what kind of \u201ctransport\u201d we\u2019re going to use, then send the message through that transport.</p>\n<p>Solar comes with two <code>Solar_Mail_Transport</code> adapters: the <code>Phpmail</code> one, which uses <a href=\"http://php.net/mail\">mail()</a> internally, and an <code>SMTP</code> factory-adapter one, which takes a little more setup but is a lot more robust.</p>\n<p>Easy one first: the mail()-based adapter.</p>\n<pre><code>$mail = Solar::factory('Solar_Mail_Message');\n// .. build the message ...\n\n// build a transport and send the message\n$transport = Solar::factory('Solar_Mail_Transport', array(\n    'adapter' =&gt; 'Solar_Mail_Transport_Adapter_Phpmail'\n));\n\n$transport-&gt;send($mail);\n</code></pre>\n<p>The SMTP factory-adapter is a little more complicated, but still not too hard. We need to build an <a href=\"http://solarphp.com/package/Solar_Smtp\">SMTP connection object</a>, then tell the SMTP transport adapter to use it, <em>then</em> send the message.</p>\n<pre><code>$mail = Solar::factory('Solar_Mail_Message');\n// ...\n\n// build an SMTP connection object\n$smtp = Solar::factory('Solar_Smtp', array(\n    'adapter' =&gt; 'Solar_Smtp_Adapter_NoAuth',\n    'host'    =&gt; 'mail.example.com',\n));\n\n// build a transport and send the message\n$transport = Solar::factory('Solar_Mail_Transport', array(\n    'adapter' =&gt; 'Solar_Mail_Transport_Adapter_Smtp',\n    'smtp'    =&gt; $smtp,\n));\n\n$transport-&gt;send($mail);\n</code></pre>\n<p>The SMTP connection object is itself a factory, and has adapters for various kinds of authentication:</p>\n<ul>\n<li>\n<a href=\"http://solarphp.com/class/Solar_Smtp_Adapter_NoAuth\">none</a> (the default)</li>\n<li>\n<a href=\"http://solarphp.com/class/Solar_Smtp_Adapter_PlainAuth\">plain</a> </li>\n<li><a href=\"http://solarphp.com/class/Solar_Smtp_Adapter_LoginAuth\">login</a></li>\n<li><a href=\"http://solarphp.com/class/Solar_Smtp_Adapter_CramMd5Auth\">CRAM-MD5</a></li>\n</ul>\n<h3>Transport Dependency-Injection</h3>\n<p>Let\u2019s say you always use SMTP with plain authentication when sending a message.  You can register the transport objects in your bootstrap file or your <a href=\"http://solarphp.com/class/Solar_Controller_Page\"><code>Solar_Controller_Page::_setup()</code></a> method so they are available throughout the application:</p>\n<pre><code>// build a Solar_Smtp object\n$smtp = Solar::factory('Solar_Smtp', array(\n    'adapter'  =&gt; 'Solar_Smtp_Adapter_PlainAuth',\n    'username' =&gt; 'pmjones',\n    'password' =&gt; 'secret',\n    'host'     =&gt; 'mail.example.com',\n));\n\n// register it as 'smtp'\nSolar::register('smtp', $smtp);\n\n// build a Solar_Mail_Transport object with the SMTP object injected\n$transport = Solar::factory('Solar_Mail_Transport', array(\n    'adapter' =&gt; 'Solar_Mail_Transport_Adapter_Smtp',\n    'smtp'    =&gt; 'smtp', // uses the registered 'smtp' object\n);\n\n// register the transport as 'mail-transport'\nSolar::register('mail-transport', $transport);\n</code></pre>\n<p>Now when you create a new mail message, you can tell it that there\u2019s a transport already available, and call send() directly on the message.</p>\n<pre><code>$mail = Solar::factory('Solar_Mail_Message', array(\n    'transport' =&gt; 'mail-transport',\n));\n\n// ... build the message, and then:\n$mail-&gt;send();\n</code></pre>\n<h3>Automation Via Config File Settings</h3>\n<p>Finally, you can take the configuration of the SMTP, transport, and mail objects entirely out of your logic, and put it all in the <a href=\"http://solarphp.com/manual/Solar/Config_file\">Solar config file</a>.</p>\n<p>Then you can lazy-load the objects from the registry, and they will automatically have all the right settings. The various dependency objects will be lazy-loaded automatically for you, since <a href=\"http://solarphp.com/manual/Solar/Dependency_injection\">dependency injection</a> is a core component of Solar.</p>\n<p>In your Solar.config.php file:</p>\n<pre><code>// configure SMTP\n$config['Solar_Smtp'] = array(\n    'adapter'  =&gt; 'Solar_Smtp_Adapter_PlainAuth',\n    'username' =&gt; 'pmjones',\n    'password' =&gt; 'secret',\n    'host'     =&gt; 'mail.example.com',\n);\n\n// configure mail transport\n$config['Solar_Mail_Transport'] = array(\n    'adapter' =&gt; 'Solar_Mail_Transport_Adapter_Smtp',\n    'smtp'    =&gt; 'smtp',\n);\n\n// tell all mail messages to use the registered 'mail-transport'\n$config['Solar_Mail_Message']['transport'] = 'mail-transport';\n</code></pre>\n<p>Then all you have to do in your setup logic is register class names instead of objects \u2026</p>\n<pre><code>Solar::register('smtp', 'Solar_Smtp');\nSolar::register('mail-transport', 'Solar_Mail_Transport');\n</code></pre>\n<p>\u2026 which will cause those objects to be created only at the moment they are first called as depndencies.</p>\n<p>Now you can send an email message very simply:</p>\n<pre><code>// create and build a message\n$mail = Solar::factory('Solar_Mail_Message');\n// ...\n\n// send the message; this creates the SMTP and mail-transport objects\n// from the config-file settings, and sends the message trough the\n// registered transport.\n$mail-&gt;send();\n</code></pre>\n<p>Using the config-file-centered process instead of the logic-centered process means that you can have all your settings in one place for use throughout your application.  You can even change adapters from the config file without changing any of the mail-sending code, as long as you keep the same registry names.</p>\n<h3>Conclusion</h3>\n<p>That\u2019s a whirlwind tour of how to send mail in <a href=\"http://solarphp.com\">Solar</a>.  If you have questions or comments, please feel free to leave them here, or join the <a href=\"http://solarphp.com/project/mailing-list\">Solar mailing list</a> \u2013 we\u2019d love to have you around.</p>\n"
}
