forked from arkanis/smtp_send
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Imported current version from 2018-04-24.
- Loading branch information
Showing
3 changed files
with
882 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,366 @@ | ||
# smtp_send | ||
|
||
This is a single PHP function to send mails (~90 LOC). The one function in | ||
`smtp_send.php` is all you need. So you can just download that file and | ||
`require` it or copy and paste the code to wherever you need it. | ||
|
||
Feel free to open an issue if something doesn't work as expected. Sending a push | ||
request is even better. | ||
|
||
`smtp_send` sends mails directly via SMTP. It uses `STARTTLS` when the server | ||
supports it. More examples are further down. Basic usage: | ||
|
||
$message = <<<EOD | ||
From: "Mr. Sender" <[email protected]> | ||
To: "Mr. Receiver" <[email protected]> | ||
Subject: SMTP Test | ||
Date: Thu, 21 Dec 2017 16:01:07 +0200 | ||
Content-Type: text/plain; charset=utf-8 | ||
|
||
Hello there. Just a small test. 😊 | ||
End of message. | ||
EOD; | ||
smtp_send('[email protected]', '[email protected]', $message, 'mail.dep1.example.com', 587, array( | ||
'user' => 'sender', | ||
'pass' => 'secret' | ||
)); | ||
|
||
|
||
Signature and parameters | ||
------------------------ | ||
|
||
~~~ php | ||
bool smtp_send($from, $to, $message, $smtp_server, $smtp_port, $options = array()) | ||
~~~ | ||
|
||
__$from__: The mail address of the sender. This is given directly to the SMTP | ||
server and is independent of the `From` header in the message. | ||
|
||
If an addresses contains unquoted ">" characters the function aborts and | ||
returns `false`. Otherwise an address could be used ot inject further SMTP | ||
commands into the connection. A properly quoted address looks like this: | ||
`"foo\>bar"@example.com` (I know it looks strange but that's the RFC). | ||
|
||
__$to__: The mail address of the receiver(s) given to the SMTP server. Again | ||
this is independent from the `To` header(s) in the message. If an array of | ||
mail addresses is given the mail is send to each address (one `RCPT TO` | ||
command is send for each address). Just like in `$from` ">" characters have | ||
to be quoted or the function returns `false`. | ||
|
||
You can send mails to many people without giving away everyones mail | ||
address (BCC, Blind Carbon Copy). For that set the `To` header _within_ the | ||
mail to something like "Undisclosed recipients:;" while listing all | ||
addresses in the `$to` parameter. Then the SMTP server will send the mail | ||
to everyone but the mail doesn’t contain their addresses (example further | ||
down). | ||
|
||
__$message__: The source code of the mail. You can find examples below or in | ||
[RFC5322 appendix A][1]. `\n` line breaks are automatically | ||
converted to `\r\n` (CRLF) so you can just use normal line breaks when | ||
constructing it. | ||
|
||
[1]: https://tools.ietf.org/html/rfc5322#appendix-A | ||
|
||
__$smtp_server__ and __$smtp_port__: The hostname (or IP address) and port of | ||
the SMTP server. That’s the server you submit the mail to and it’ll figure | ||
out how it gets there. The function will use [`fsockopen()`][2] to connect | ||
to that server and submit the mail via SMTP commands. Since `fsockopen()` | ||
supports [transports][3] you can use TLS or UNIX domain sockets for | ||
submission (again, see code examples further down). | ||
|
||
Example hostnames: `127.0.0.1`, `::1`, `mail.example.com`, | ||
`tls://mail.example.com` | ||
|
||
Often used ports: | ||
|
||
- 587 (starts without encryption but usually secured with `STARTTLS`) | ||
- 465 (server expects connection to use the TLS transport) | ||
- 25 (usually for communication between mail servers) | ||
|
||
[2]: http://php.net/fsockopen | ||
[3]: http://php.net/transports | ||
|
||
__$options__: An array with further arguments that are only needed for | ||
extended functionality like SMTP authentication or some down to the wire | ||
details. | ||
|
||
- `user` and `pass` keys: SMTP user name and password. Both have to be set | ||
to enable authentication. Right now only PLAIN authentication is | ||
supported. | ||
Default when not specified: Don't do SMTP authentication. | ||
- `timeout`: The timeout in seconds used by `fsockopen()`. If it can't | ||
connect to the SMTP server in that time the function aborts. | ||
Default when not specified: Return value of `ini_get("default_socket_timeout")`. | ||
- `client_domain`: The client identification send to the server with the | ||
`EHLO` greeting. Looks like servers ignore it. I don’t know what they | ||
should do with it. | ||
Default when not specified: Return value of `gethostname()`. | ||
|
||
Return value | ||
------------ | ||
|
||
The function returns `true` if the mail was submitted, `false` if an error | ||
occurred. No detailed error messages are supported but feel free to add it to | ||
the code if needed. | ||
|
||
Code examples | ||
------------- | ||
|
||
Sending a text mail via port 587 with SMTP authentication. `STARTTLS` is | ||
automatically used when the server supports it. Otherwise the connection will | ||
be unencrypted. | ||
|
||
$message = <<<EOD | ||
From: "Mr. Sender" <[email protected]> | ||
To: "Mr. Receiver" <[email protected]> | ||
Subject: SMTP Test | ||
Date: Thu, 21 Dec 2017 16:01:07 +0200 | ||
Content-Type: text/plain; charset=utf-8 | ||
|
||
Hello there. Just a small test. 😊 | ||
End of message. | ||
EOD; | ||
smtp_send('[email protected]', '[email protected]', $message, 'mail.example.com', 587, array( | ||
'user' => 'sender', | ||
'pass' => 'secret' | ||
)); | ||
|
||
* * * | ||
|
||
Sending a text mail via port 465. The server expects an encrypted connection | ||
so we have to use the TLS transport (notice the `tls://` at the start of the | ||
hostname). | ||
|
||
$message = <<<EOD | ||
From: "Mr. Sender" <[email protected]> | ||
To: "Mr. Receiver" <[email protected]> | ||
Subject: SMTP Test | ||
Date: Thu, 21 Dec 2017 16:01:07 +0200 | ||
Content-Type: text/plain; charset=utf-8 | ||
|
||
Hello there. Just a small test. 😊 | ||
End of message. | ||
EOD; | ||
smtp_send('[email protected]', '[email protected]', $message, 'tls://mail.example.com', 465, array( | ||
'user' => 'sender', | ||
'pass' => 'secret' | ||
)); | ||
|
||
* * * | ||
|
||
Sending a mail to many recipients without giving away their addresses to | ||
everyone (BCC, Blind Carbon Copy): | ||
|
||
$message = <<<EOD | ||
From: "Mr. Sender" <[email protected]> | ||
To: Undisclosed recipients:; | ||
Subject: SMTP BCC Test | ||
Date: Thu, 21 Dec 2017 16:01:07 +0200 | ||
Content-Type: text/plain; charset=utf-8 | ||
|
||
Try to figure out who else got this message… | ||
EOD; | ||
smtp_send('[email protected]', [ | ||
'[email protected]', '[email protected]', '[email protected]' | ||
], $message, 'mail.example.com', 587, array( | ||
'user' => 'sender', | ||
'pass' => 'secret' | ||
)); | ||
|
||
* * * | ||
|
||
Sending an HTML mail: | ||
|
||
$message = <<<EOD | ||
From: "Mr. Sender" <[email protected]> | ||
To: "Mr. Receiver" <[email protected]> | ||
Subject: SMTP Test | ||
Date: Thu, 21 Dec 2017 16:01:07 +0200 | ||
MIME-Version: 1.0 | ||
Content-Type: text/html; charset=utf-8 | ||
|
||
<html> | ||
<head><title>An HTML mail</title></head> | ||
<body> | ||
<h1>See, HTML!</h1> | ||
<p>Have fun 😊</p> | ||
</body> | ||
</html> | ||
EOD; | ||
smtp_send('[email protected]', '[email protected]', $message, 'mail.example.com', 587, array( | ||
'user' => 'sender', | ||
'pass' => 'secret' | ||
)); | ||
|
||
* * * | ||
|
||
Sending a mail with an attachment ("mixed content"): | ||
|
||
$base64_file_data = base64_encode(file_get_contents("file.xyz")); | ||
$message = <<<EOD | ||
From: "Mr. Sender" <[email protected]> | ||
To: "Mr. Receiver" <[email protected]> | ||
Subject: SMTP Attachment Test | ||
Date: Thu, 21 Dec 2017 16:01:07 +0200 | ||
MIME-Version: 1.0 | ||
Content-Type: multipart/mixed; boundary="XXXXXXXXXX" | ||
|
||
This is the preamble. It's ignored. | ||
--XXXXXXXXXX | ||
Content-Type: text/plain; charset=utf-8 | ||
|
||
This is a mail with an attachment. Have fun with it. | ||
--XXXXXXXXXX | ||
Content-Type: application/octet-stream; name="file.xyz" | ||
Content-Transfer-Encoding: base64 | ||
Content-Disposition: attachment; filename="file.xyz" | ||
|
||
$base64_file_data | ||
--XXXXXXXXXX-- | ||
This is the epilogue. It's also ignored. | ||
EOD; | ||
smtp_send('[email protected]', '[email protected]', $message, 'mail.example.com', 587, array( | ||
'user' => 'sender', | ||
'pass' => 'secret' | ||
)); | ||
|
||
Based on the example in [RFC 2046 page 21][4]. The line "--XXXXXXXXXX" is the | ||
boundary between the different parts and must not occur in any of them. | ||
"--XXXXXXXXXX--" (note "--" at the end) signals the end of the last part. | ||
Everything after that is ignored. Usually the boundary is a random | ||
alphanumeric string with 20 to 30 characters. I just chose "XXXXXXXXXX" for | ||
better visibility. | ||
|
||
[4]: https://tools.ietf.org/html/rfc2046#page-21 | ||
|
||
Some mail clients use the filename in Content-Type name, some the one in | ||
Content-Disposition filename. So set both. | ||
|
||
Please set the Content-Type of the attachment to a proper value (e.g. | ||
"image/jpeg" for *.jpg files). This helps mail clients to select a proper | ||
program for opening the attachment. "application/octet-stream" is the MIME | ||
type for a binary file with unknown content. | ||
|
||
You can also use "Content-Disposition: inline" instead of attachment. In that | ||
case the browser tries to show the attachment as part of the message. This is | ||
often used for images. | ||
|
||
* * * | ||
|
||
Sending a mail with the same content as text and HTML (alternate content): | ||
|
||
$message = <<<EOD | ||
From: "Mr. Sender" <[email protected]> | ||
To: "Mr. Receiver" <[email protected]> | ||
Subject: SMTP Alternate Content Test | ||
Date: Thu, 21 Dec 2017 16:01:07 +0200 | ||
MIME-Version: 1.0 | ||
Content-Type: multipart/alternative; boundary="XXXXXXXXXX" | ||
|
||
This is the preamble. It's ignored. | ||
--XXXXXXXXXX | ||
Content-Type: text/plain; charset=utf-8 | ||
|
||
A message with a list: | ||
|
||
- Point A | ||
- Point B | ||
- Point C | ||
|
||
--XXXXXXXXXX | ||
Content-Type: text/html; charset=utf-8 | ||
|
||
<html> | ||
<head><title>SMTP Alternate Content Test</title></head> | ||
<body> | ||
<p>A message with a list:</p> | ||
<ul> | ||
<li>Point A</li> | ||
<li>Point B</li> | ||
<li>Point C</li> | ||
</ul> | ||
</body> | ||
</html> | ||
--XXXXXXXXXX-- | ||
This is the epilogue. It's also ignored. | ||
EOD; | ||
smtp_send('[email protected]', '[email protected]', $message, 'mail.example.com', 587, array( | ||
'user' => 'sender', | ||
'pass' => 'secret' | ||
)); | ||
|
||
* * * | ||
|
||
You can also nest mixed and alternative content. For example to send a | ||
message with an attachment where the text part is provided as plain text and | ||
HTML. | ||
|
||
$base64_file_data = base64_encode(file_get_contents("file.xyz")); | ||
$message = <<<EOD | ||
From: "Mr. Sender" <[email protected]> | ||
To: "Mr. Receiver" <[email protected]> | ||
Subject: SMTP Alternate and Mixed Content Test | ||
Date: Thu, 21 Dec 2017 16:01:07 +0200 | ||
MIME-Version: 1.0 | ||
Content-Type: multipart/mixed; boundary="XXXXXXXXXX" | ||
|
||
--XXXXXXXXXX | ||
Content-Type: multipart/alternative; boundary="YYYYYYYYYY" | ||
|
||
--YYYYYYYYYY | ||
Content-Type: text/plain; charset=utf-8 | ||
|
||
A message with a list: | ||
|
||
- Point A | ||
- Point B | ||
- Point C | ||
|
||
--YYYYYYYYYY | ||
Content-Type: text/html; charset=utf-8 | ||
|
||
<html> | ||
<head><title>SMTP Alternate and Mixed Content Test</title></head> | ||
<body> | ||
<p>A message with a list:</p> | ||
<ul> | ||
<li>Point A</li> | ||
<li>Point B</li> | ||
<li>Point C</li> | ||
</ul> | ||
</body> | ||
</html> | ||
--YYYYYYYYYY-- | ||
--XXXXXXXXXX | ||
Content-Type: application/octet-stream; name="file.xyz" | ||
Content-Transfer-Encoding: base64 | ||
Content-Disposition: attachment; filename="file.xyz" | ||
|
||
$base64_file_data | ||
--XXXXXXXXXX-- | ||
EOD; | ||
smtp_send('[email protected]', '[email protected]', $message, 'mail.example.com', 587, array( | ||
'user' => 'sender', | ||
'pass' => 'secret' | ||
)); | ||
|
||
|
||
License | ||
------- | ||
|
||
`smtp_send()` function © 2018 Stephan Soller | ||
Distributed under the MIT License | ||
|
||
Version history | ||
--------------- | ||
|
||
- 2018-04-24 by Stephan Soller <[email protected]> | ||
Added code to reject mail addresses that could potentially inject other | ||
SMTP commands. | ||
|
||
- 2018-03-12 by Stephan Soller <[email protected]> | ||
Multiple greeting lines from the server were not correctly consumed. This | ||
prevented mail submission on some SMTP servers. | ||
|
||
- 2014-09-14 by Stephan Soller <[email protected]> | ||
Wrote function to be independent of PHPs mail configuration. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
ob_start(function($markdown_text){ | ||
file_put_contents("README.md", $markdown_text); | ||
}); | ||
|
||
?> | ||
# smtp_send | ||
|
||
This is a single PHP function to send mails (~90 LOC). The one function in | ||
`smtp_send.php` is all you need. So you can just download that file and | ||
`require` it or copy and paste the code to wherever you need it. | ||
|
||
Feel free to open an issue if something doesn't work as expected. Sending a push | ||
request is even better. | ||
|
||
<?php | ||
preg_match("/ \/\*\* (.+?) \*\/ /xs", file_get_contents("smtp_send.php"), $matches); | ||
$function_documentation = preg_replace("/^\s*\* /m", "", $matches[1]); | ||
echo(trim($function_documentation)); | ||
?> |
Oops, something went wrong.