Let user define linesep + documentation

This commit is contained in:
Inkrementator 2024-04-19 14:21:32 +02:00
parent 97313ae98e
commit 318b0fd320
1 changed files with 20 additions and 11 deletions

31
email.d
View File

@ -75,6 +75,15 @@ class EmailMessage {
string[] headers; string[] headers;
/** If you use the send method with an SMTP server, you don't want to change this.
*
* While RFC 2045 mandates CRLF as a lineseperator, there are some edge-cases where this won't work.
* When passing the E-Mail string to a unix program which handles communication with the SMTP server, some (i.e. qmail)
* expect the system lineseperator (LF) instead.
* Notably, the google mail REST API will choke on CRLF lineseps and produce strange emails (as of 2024).
*/
string linesep = "\r\n";
private bool isMime = false; private bool isMime = false;
private bool isHtml = false; private bool isHtml = false;
@ -213,7 +222,7 @@ class EmailMessage {
auto mimeAttachment = new MimeContainer(attachment.type ~ "; name=\""~attachment.filename~"\""); auto mimeAttachment = new MimeContainer(attachment.type ~ "; name=\""~attachment.filename~"\"");
mimeAttachment.headers ~= "Content-Transfer-Encoding: base64"; mimeAttachment.headers ~= "Content-Transfer-Encoding: base64";
mimeAttachment.headers ~= "Content-ID: <" ~ attachment.id ~ ">"; mimeAttachment.headers ~= "Content-ID: <" ~ attachment.id ~ ">";
mimeAttachment.content = encodeBase64Mime(cast(const(ubyte)[]) attachment.content); mimeAttachment.content = encodeBase64Mime(cast(const(ubyte)[]) attachment.content, this.linesep);
mimeRelated.stuff ~= mimeAttachment; mimeRelated.stuff ~= mimeAttachment;
} }
@ -235,7 +244,7 @@ class EmailMessage {
if(attachment.id.length) if(attachment.id.length)
mimeAttachment.headers ~= "Content-ID: <" ~ attachment.id ~ ">"; mimeAttachment.headers ~= "Content-ID: <" ~ attachment.id ~ ">";
mimeAttachment.content = encodeBase64Mime(cast(const(ubyte)[]) attachment.content); mimeAttachment.content = encodeBase64Mime(cast(const(ubyte)[]) attachment.content, this.linesep);
mimeMixed.stuff ~= mimeAttachment; mimeMixed.stuff ~= mimeAttachment;
} }
@ -243,7 +252,7 @@ class EmailMessage {
} }
headers ~= top.contentType; headers ~= top.contentType;
msgContent = top.toMimeString(true); msgContent = top.toMimeString(true, this.linesep);
} else { } else {
headers ~= "Content-Type: text/plain; charset=UTF-8"; headers ~= "Content-Type: text/plain; charset=UTF-8";
msgContent = textBody; msgContent = textBody;
@ -254,9 +263,9 @@ class EmailMessage {
msg.reserve(htmlBody.length + textBody.length + 1024); msg.reserve(htmlBody.length + textBody.length + 1024);
foreach(header; headers) foreach(header; headers)
msg ~= header ~ "\r\n"; msg ~= header ~ this.linesep;
if(msg.length) // has headers if(msg.length) // has headers
msg ~= "\r\n"; msg ~= this.linesep;
msg ~= msgContent; msg ~= msgContent;
@ -616,28 +625,28 @@ class MimeContainer {
} }
string toMimeString(bool isRoot = false) { string toMimeString(bool isRoot = false, string linesep="\r\n") {
string ret; string ret;
if(!isRoot) { if(!isRoot) {
ret ~= contentType; ret ~= contentType;
foreach(header; headers) { foreach(header; headers) {
ret ~= "\r\n"; ret ~= linesep;
ret ~= header; ret ~= header;
} }
ret ~= "\r\n\r\n"; ret ~= linesep ~ linesep;
} }
ret ~= content; ret ~= content;
foreach(idx, thing; stuff) { foreach(idx, thing; stuff) {
assert(boundary.length); assert(boundary.length);
ret ~= "\r\n--" ~ boundary ~ "\r\n"; ret ~= linesep ~ "--" ~ boundary ~ linesep;
ret ~= thing.toMimeString(false); ret ~= thing.toMimeString(false, linesep);
} }
if(boundary.length) if(boundary.length)
ret ~= "\r\n--" ~ boundary ~ "--"; ret ~= linesep ~ "--" ~ boundary ~ "--";
return ret; return ret;
} }