Skip to content

Commit

Permalink
feat: v5.0.0! bug fixes and lib update
Browse files Browse the repository at this point in the history
fixes issue kaisellgren#172
fixes issue kaisellgren#171
fixes issue kaisellgren#167
fixes issue kaisellgren#152

improved document for cid (issue kaisellgren#104)
  • Loading branch information
close2 authored and fsw committed Nov 16, 2023
1 parent 1bfa369 commit a6cb3df
Show file tree
Hide file tree
Showing 8 changed files with 611 additions and 0 deletions.
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies:
mime: '^1.0.0'
path: '^1.7.0'
pedantic: '^1.9.2'
meta: '^1.3.0'

dev_dependencies:
args: '^2.0.0'
Expand Down
Binary file added test/exploits_of_a_mom.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
334 changes: 334 additions & 0 deletions test/messages/message_all.dart

Large diffs are not rendered by default.

146 changes: 146 additions & 0 deletions test/messages/message_helpers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
part of message_out_test;

String e(String stringToEscape) => RegExp.escape(stringToEscape);

const dateHeader =
'date: [\\w]{3}, [0-9]+ [\\w]{3} 2[0-9]{3} [0-9]{1,2}:[0-9]{2}:[0-9]{2} \\+[0-9]{4}\r\n';
const contentTypeHeaderAlternative =
'content-type: multipart/alternative;boundary="mailer-\\?=(?<boundaryAlternative>.*)"\r\n';
const boundaryAlternative = '--mailer-\\?=\\k<boundaryAlternative>\r\n';
const boundaryEndAlternative = '--mailer-\\?=\\k<boundaryAlternative>--\r\n';

const contentTypeHeaderMixed =
'content-type: multipart/mixed;boundary="mailer-\\?=(?<boundaryMixed>.*)"\r\n';
const boundaryMixed = '--mailer-\\?=\\k<boundaryMixed>\r\n';
const boundaryEndMixed = '--mailer-\\?=\\k<boundaryMixed>--\r\n';

const contentTypeHeaderRelated =
'content-type: multipart/related;boundary="mailer-\\?=(?<boundaryRelated>.*)"\r\n';
const boundaryRelated = '--mailer-\\?=\\k<boundaryRelated>\r\n';
const boundaryEndRelated = '--mailer-\\?=\\k<boundaryRelated>--\r\n';

const defaultSubject = 'utf8 mail😀';
final defaultSubjectRegExpUtf8 = e('utf8 mail😀');
final defaultSubjectRegExpNotUtf8 = e('=?utf-8?B?dXRmOCBtYWls8J+YgA==?=');

final defaultFromRegExp = e('Name <[email protected]>');

final defaultText = 'utf8😀t';
final defaultHtml = 'utf8😀h';

String mailRegExpTextAndHtml(String subject,
{String? text, String? html, String? fromHeader}) {
return '^'
'subject: $subject\r\n'
'from: ${fromHeader ?? defaultFromRegExp}\r\n' +
e('to: [email protected]\r\n') +
dateHeader +
e('x-mailer: Dart Mailer library\r\n') +
e('mime-version: 1.0\r\n') +
contentTypeHeaderAlternative +
e('\r\n') +
boundaryAlternative +
e('content-type: text/plain; charset=utf-8\r\n') +
e('content-transfer-encoding: base64\r\n') +
e('\r\n') +
'${text ?? e('dXRmOPCfmIB0DQo=')}\r\n' +
e('\r\n') +
boundaryAlternative +
e('content-type: text/html; charset=utf-8\r\n') +
e('content-transfer-encoding: base64\r\n') +
e('\r\n') +
'${html ?? e('dXRmOPCfmIBoDQo=')}\r\n' +
e('\r\n') +
boundaryEndAlternative +
e('\r\n') +
r'$';
}

class TestAttachment {
final String name;
final String type;
final String disposition;
final String content;

TestAttachment(this.name, this.type, this.disposition, this.content);
}

String mailRegExpTextHtmlAndInlineAttachments(String subject,
List<TestAttachment> inlineAttachments, List<TestAttachment> attachments,
{String? text, String? html, String? fromHeader}) {
var result = '^'
'subject: $subject\r\n'
'from: ${fromHeader ?? defaultFromRegExp}\r\n' +
e('to: [email protected]\r\n') +
dateHeader +
e('x-mailer: Dart Mailer library\r\n') +
e('mime-version: 1.0\r\n') +
contentTypeHeaderMixed +
e('\r\n') +
boundaryMixed +
contentTypeHeaderAlternative +
e('\r\n') +
boundaryAlternative +
e('content-type: text/plain; charset=utf-8\r\n') +
e('content-transfer-encoding: base64\r\n') +
e('\r\n') +
'${text ?? e('dXRmOPCfmIB0DQo=')}\r\n' +
e('\r\n') +
boundaryAlternative +
contentTypeHeaderRelated +
e('\r\n') +
boundaryRelated +
e('content-type: text/html; charset=utf-8\r\n') +
e('content-transfer-encoding: base64\r\n') +
e('\r\n') +
'${html ?? e('dXRmOPCfmIBoDQo=')}\r\n' +
e('\r\n');
inlineAttachments.forEach((a) {
result += boundaryRelated +
e('content-type: ${a.type}\r\n') +
e('content-transfer-encoding: base64\r\n') +
e('content-disposition: ${a.disposition}\r\n') +
e('\r\n') +
e('${a.name}\r\n') +
e('\r\n');
});
result += boundaryEndRelated + e('\r\n');
result += boundaryEndAlternative + e('\r\n');
attachments.forEach((a) {
result += boundaryMixed +
e('content-type: ${a.type}\r\n') +
e('content-transfer-encoding: base64\r\n') +
e('content-disposition: ${a.disposition}\r\n') +
e('\r\n') +
e('${a.name}\r\n') +
e('\r\n');
});

result += boundaryEndMixed + '\r\n' + r'$';
return result;
}

String mailRegExpTextOrHtml(String subject,
{String? text, String? html, String? fromHeader}) {
return '^'
'subject: $subject\r\n'
'from: ${fromHeader ?? defaultFromRegExp}\r\n' +
e('to: [email protected]\r\n') +
dateHeader +
e('x-mailer: Dart Mailer library\r\n') +
e('mime-version: 1.0\r\n') +
e('content-type: text/${text != null ? 'plain' : 'html'}; charset=utf-8\r\n') +
e('content-transfer-encoding: base64\r\n') +
e('\r\n') +
'${text ?? html}\r\n' +
e('\r\n') +
r'$';
}

String mailRegExpText(String subject, {String? text, String? fromHeader}) {
return mailRegExpTextOrHtml(subject, text: text ?? e('dXRmOPCfmIB0DQo='));
}

String mailRegExpHtml(String subject, {String? html, String? fromHeader}) {
return mailRegExpTextOrHtml(subject, html: html ?? e('dXRmOPCfmIBoDQo='));
}
13 changes: 13 additions & 0 deletions test/messages/message_simple_utf8.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
part of message_out_test;


final messageSimpleUtf8 = MessageTest(
'Message with utf8 subject, html and text',
Message()
..from = Address('[email protected]', 'Name')
..recipients = ['[email protected]']
..subject = defaultSubject
..html = defaultHtml
..text = defaultText,
mailRegExpTextAndHtml(defaultSubjectRegExpUtf8),
mailRegExpTextAndHtml(defaultSubjectRegExpNotUtf8));
21 changes: 21 additions & 0 deletions test/messages/message_text_html_only.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
part of message_out_test;

final messageTextOnly = MessageTest(
'Message with utf8 subject and text',
Message()
..from = Address('[email protected]', 'Name')
..recipients = ['[email protected]']
..subject = defaultSubject
..text = defaultText,
mailRegExpText(defaultSubjectRegExpUtf8),
mailRegExpText(defaultSubjectRegExpNotUtf8));

final messageHtmlOnly = MessageTest(
'Message with utf8 subject and html',
Message()
..from = Address('[email protected]', 'Name')
..recipients = ['[email protected]']
..subject = defaultSubject
..html = defaultHtml,
mailRegExpHtml(defaultSubjectRegExpUtf8),
mailRegExpHtml(defaultSubjectRegExpNotUtf8));
19 changes: 19 additions & 0 deletions test/messages/message_utf8_from_header.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
part of message_out_test;

final _utf8Address = Address('[email protected]', 'Name😀1');
final _utf8FromHeaderRegexp = e('Name😀1 <[email protected]>');
final _utf8FromHeaderEncodedRegexp =
e('=?utf-8?B?TmFtZfCfmIAx?= <[email protected]>');

final messageUtf8FromHeader = MessageTest(
'Message with utf8 subject, html and text and utf8 (address) name',
Message()
..from = _utf8Address
..recipients = ['[email protected]']
..subject = defaultSubject
..html = defaultHtml
..text = defaultText,
mailRegExpTextAndHtml(defaultSubjectRegExpUtf8,
fromHeader: _utf8FromHeaderRegexp),
mailRegExpTextAndHtml(defaultSubjectRegExpNotUtf8,
fromHeader: _utf8FromHeaderEncodedRegexp));
77 changes: 77 additions & 0 deletions test/messages/message_utf8_long_subject_long_body.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
part of message_out_test;

final _subjectBelow = 's' + ('\u{1f596}' * 199);
final _subjectAbove = 's' + ('\u{1f596}' * 200);
final _textBody = 't' + ('\u{1f596}' * 300);

final _subjectBelowUtf8RegExp = e(
'=?utf-8?B?c/Cflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+Wlg==?=');

final _textBodyEncoded = e(
'dPCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+W\r\n'
'lvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+W\r\n'
'lvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+W\r\n'
'lvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+W\r\n'
'lvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+W\r\n'
'lg0K');

final _subjectAboveUtf8RegExp = e(
'=?utf-8?B?c/Cflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpbwn5aW8J+WlvCflpY=?=\r\n'
' =?utf-8?B?8J+WlvCflpY=?=');

final messageUtf8LongSubjectLongBodyBelowLineLength = MessageTest(
'Message with utf8 subject, html and text',
Message()
..from = Address('[email protected]', 'Name')
..recipients = ['[email protected]']
..subject = _subjectBelow
..html = defaultHtml
..text = _textBody,
mailRegExpTextAndHtml(_subjectBelow, text: _textBodyEncoded),
mailRegExpTextAndHtml(_subjectBelowUtf8RegExp, text: _textBodyEncoded));

final messageUtf8LongSubjectLongBodyAboveLineLength = MessageTest(
'Message with utf8 subject, html and text',
Message()
..from = Address('[email protected]', 'Name')
..recipients = ['[email protected]']
..subject = _subjectAbove
..html = defaultHtml
..text = _textBody,
mailRegExpTextAndHtml(_subjectAboveUtf8RegExp, text: _textBodyEncoded),
mailRegExpTextAndHtml(_subjectAboveUtf8RegExp, text: _textBodyEncoded));

0 comments on commit a6cb3df

Please sign in to comment.