Skip to content

Instantly share code, notes, and snippets.

Created June 19, 2011 03:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/1033711 to your computer and use it in GitHub Desktop.
Save anonymous/1033711 to your computer and use it in GitHub Desktop.
smtp protocol
/**
This is a struct which is passed to a curl function.
It contains information about the message text.
*/
private struct MailMessageData
{
immutable(char)* data; //pointer to the message text
size_t len; //how big is the message
}
/**
This is the callback to read the MailMessageData
This function's arguments are the same as fread's arguments.
*/
private extern(C) size_t read_callback(void* ptr, size_t size, size_t nmemb, void* userp)
{
// The userp argument is actually a pointer to a MailMessageData
MailMessageData* pdata = cast(MailMessageData*)userp;
//Nothing to read
if((size*nmemb) < 1)
return 0;
//Size of the data that is to be copied
size_t curl_size = nmemb * size;
//If it's larger than the data,
// then just copy all of that data
size_t to_copy = (pdata.len < curl_size) ? pdata.len : curl_size;
std.c.string.memcpy(ptr, pdata.data, to_copy);
// The reading stops when pdata.len == 0
pdata.len -= to_copy;
pdata.data += to_copy;
return to_copy;
}
/**
Basic SMTP protocol support
*/
struct SMTP {
mixin Protocol;
private bool ssl = false;
private MailMessageData message_data;
/**
Sets to the url of the SMTP server
*/
this(string url) {
curl = Curl(true);
if (url.startsWith("smtps://"))
ssl = true;
else
enforce(url.startsWith("smtp://"), "The url must be for the smtp protocol.");
curl.set(CurlOption.url, url);
if (ssl) {
curl.set(CurlOption.use_ssl, CurlUseSSL.all);
curl.set(CurlOption.ssl_verifypeer, false);
curl.set(CurlOption.ssl_verifyhost, 2);
}
}
/**
Setter for the sender's email address
*/
@property void mailFrom(string sender) {
// The sender address should be encapsulated with < and >
if (!(sender[0] == '<' && sender[$ - 1] == '>'))
sender = '<' ~ sender ~ '>';
curl.set(CurlOption.mail_from, sender);
}
/**
Setter for the recipient email addresses
*/
@property void mailTo(string[] recipients) {
curl_slist* recipients_list = null;
foreach(recipient; recipients) {
if (!(recipient[0] == '<' && recipient[$-1] == '>'))
recipient = '<' ~ recipient ~ '>';
recipients_list = curl_slist_append(recipients_list, cast(char*)toStringz(recipient));
}
curl.set(CurlOption.mail_rcpt, cast(void*)recipients_list);
}
/**
Sets the message body text
*/
@property void message(string msg) {
message_data = MailMessageData(msg.ptr, msg.length);
curl.set(CurlOption.infile, cast(void*)&message_data);
curl.set(CurlOption.readfunction, cast(void*)&read_callback);
}
/**
Performs the request as configured
*/
void perform() {
curl.perform;
}
/**
Convenience function that sends an email.
Example:
----
SMTP.sendMail("smtps://smtp.gmail.com", "<from.addr@gmail.com>", ["<to.addr@gmail.com>"], "Hi");
----
*/
static void sendMail(string url, string from_addr, string[] to_addrs,
string msg, string username = "", string password = "") {
auto client = SMTP(url);
client.mailFrom = from_addr;
client.mailTo = to_addrs;
client.message = msg;
if (username || password)
client.setAuthentication(username, password);
client.perform;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment