handle base64 html email

This commit is contained in:
Adam D. Ruppe 2017-05-05 16:28:31 -04:00
parent b777074e88
commit c70ce55098
1 changed files with 54 additions and 19 deletions

73
email.d
View File

@ -11,20 +11,23 @@ import arsd.characterencodings;
// SEE ALSO: std.net.curl.SMTP // SEE ALSO: std.net.curl.SMTP
///
struct RelayInfo { struct RelayInfo {
string server; string server; ///
string username; string username; ///
string password; string password; ///
} }
///
struct MimeAttachment { struct MimeAttachment {
string type; string type; ///
string filename; string filename; ///
const(void)[] content; const(void)[] content; ///
string id; string id; ///
} }
/// For OUTGOING email
class EmailMessage { class EmailMessage {
void setHeader(string name, string value) { void setHeader(string name, string value) {
headers ~= name ~ ": " ~ value; headers ~= name ~ ": " ~ value;
@ -224,6 +227,7 @@ class EmailMessage {
} }
} }
///
void email(string to, string subject, string message, string from, RelayInfo mailServer = RelayInfo("smtp://localhost")) { void email(string to, string subject, string message, string from, RelayInfo mailServer = RelayInfo("smtp://localhost")) {
auto msg = new EmailMessage(); auto msg = new EmailMessage();
msg.from = from; msg.from = from;
@ -237,7 +241,7 @@ void email(string to, string subject, string message, string from, RelayInfo mai
import std.conv; import std.conv;
// for reading /// for reading
class MimePart { class MimePart {
string[] headers; string[] headers;
immutable(ubyte)[] content; immutable(ubyte)[] content;
@ -520,12 +524,15 @@ class MimeContainer {
} }
import std.algorithm : startsWith; import std.algorithm : startsWith;
///
class IncomingEmailMessage { class IncomingEmailMessage {
///
this(string[] lines) { this(string[] lines) {
auto lns = cast(immutable(ubyte)[][])lines; auto lns = cast(immutable(ubyte)[][])lines;
this(lns, false); this(lns, false);
} }
///
this(ref immutable(ubyte)[][] mboxLines, bool asmbox=true) { this(ref immutable(ubyte)[][] mboxLines, bool asmbox=true) {
enum ParseState { enum ParseState {
@ -745,6 +752,14 @@ class IncomingEmailMessage {
foreach (char ch; textMessageBody) if (ch > ' ' && ch < 127) mmb ~= ch; foreach (char ch; textMessageBody) if (ch > ' ' && ch < 127) mmb ~= ch;
textMessageBody = convertToUtf8Lossy(Base64.decode(mmb), charset); textMessageBody = convertToUtf8Lossy(Base64.decode(mmb), charset);
} }
if(htmlMessageBody.length) {
// alas, phobos' base64 decoder cannot accept ranges, so we have to allocate here
char[] mmb;
mmb.reserve(htmlMessageBody.length);
foreach (char ch; htmlMessageBody) if (ch > ' ' && ch < 127) mmb ~= ch;
htmlMessageBody = convertToUtf8Lossy(Base64.decode(mmb), charset);
}
break; break;
default: default:
// nothing needed // nothing needed
@ -758,6 +773,7 @@ class IncomingEmailMessage {
} }
} }
///
@property bool hasGPGSignature () const nothrow @trusted @nogc { @property bool hasGPGSignature () const nothrow @trusted @nogc {
MimePart mime = cast(MimePart)gpgmime; // sorry MimePart mime = cast(MimePart)gpgmime; // sorry
if (mime is null) return false; if (mime is null) return false;
@ -768,6 +784,7 @@ class IncomingEmailMessage {
return true; return true;
} }
///
ubyte[] extractGPGData () const nothrow @trusted { ubyte[] extractGPGData () const nothrow @trusted {
if (!hasGPGSignature) return null; if (!hasGPGSignature) return null;
MimePart mime = cast(MimePart)gpgmime; // sorry MimePart mime = cast(MimePart)gpgmime; // sorry
@ -800,29 +817,46 @@ class IncomingEmailMessage {
return cast(ubyte[])res; return cast(ubyte[])res;
} }
///
immutable(ubyte)[] extractGPGSignature () const nothrow @safe @nogc { immutable(ubyte)[] extractGPGSignature () const nothrow @safe @nogc {
if (!hasGPGSignature) return null; if (!hasGPGSignature) return null;
return gpgmime.stuff[1].content; return gpgmime.stuff[1].content;
} }
string[string] headers; string[string] headers; ///
string subject; string subject; ///
string htmlMessageBody; string htmlMessageBody; ///
string textMessageBody; string textMessageBody; ///
string from; string from; ///
string to; string to; ///
bool textAutoConverted; bool textAutoConverted; ///
MimeAttachment[] attachments; MimeAttachment[] attachments; ///
// gpg signature fields // gpg signature fields
string gpgalg; string gpgalg; ///
string gpgproto; string gpgproto; ///
MimePart gpgmime; MimePart gpgmime; ///
string fromEmailAddress() {
auto i = from.indexOf("<");
if(i == -1)
return from;
auto e = from.indexOf(">");
return from[i + 1 .. e];
}
string toEmailAddress() {
auto i = to.indexOf("<");
if(i == -1)
return to;
auto e = to.indexOf(">");
return to[i + 1 .. e];
}
} }
struct MboxMessages { struct MboxMessages {
@ -851,6 +885,7 @@ struct MboxMessages {
} }
} }
///
MboxMessages processMboxData(immutable(ubyte)[] data) { MboxMessages processMboxData(immutable(ubyte)[] data) {
return MboxMessages(data); return MboxMessages(data);
} }