Skip to content

Commit b83c82a

Browse files
committed
Added new MimeMessage .ctor that takes IEnumerable<Header>
See https://stackoverflow.com/questions/79297680/mimekit-how-to-create-a-textrfc822headers-from-an-eml-message-in-a-file (and to a lesser-extent: #1115)
1 parent affbcd7 commit b83c82a

File tree

2 files changed

+175
-3
lines changed

2 files changed

+175
-3
lines changed

MimeKit/MimeMessage.cs

+47
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,46 @@ public MimeMessage (params object[] args) : this (ParserOptions.Default.Clone ()
221221
MessageId = MimeUtils.GenerateMessageId ();
222222
}
223223

224+
/// <summary>
225+
/// Initialize a new instance of the <see cref="MimeMessage"/> class.
226+
/// </summary>
227+
/// <remarks>
228+
/// Creates a new <see cref="MimeMessage"/>.
229+
/// </remarks>
230+
/// <param name="headers">A list of initial message headers.</param>
231+
/// <exception cref="System.ArgumentNullException">
232+
/// <paramref name="headers"/> is <see langword="null"/>.
233+
/// </exception>
234+
public MimeMessage (IEnumerable<Header> headers)
235+
{
236+
if (headers is null)
237+
throw new ArgumentNullException (nameof (headers));
238+
239+
addresses = new Dictionary<HeaderId, InternetAddressList> ();
240+
compliance = RfcComplianceMode.Strict;
241+
242+
// initialize our address lists
243+
foreach (var id in StandardAddressHeaders) {
244+
var list = new InternetAddressList ();
245+
list.Changed += InternetAddressListChanged;
246+
addresses.Add (id, list);
247+
}
248+
249+
references = new MessageIdList ();
250+
references.Changed += ReferencesChanged;
251+
252+
if (headers is HeaderList headerList) {
253+
Headers = headerList;
254+
} else {
255+
Headers = new HeaderList (ParserOptions.Default);
256+
257+
foreach (var header in headers)
258+
Headers.Add (header);
259+
}
260+
261+
Headers.Changed += HeadersChanged;
262+
}
263+
224264
/// <summary>
225265
/// Initialize a new instance of the <see cref="MimeMessage"/> class.
226266
/// </summary>
@@ -231,6 +271,13 @@ public MimeMessage (params object[] args) : this (ParserOptions.Default.Clone ()
231271
/// <param name="to">The list of addresses in the To header.</param>
232272
/// <param name="subject">The subject of the message.</param>
233273
/// <param name="body">The body of the message.</param>
274+
/// <exception cref="System.ArgumentNullException">
275+
/// <para><paramref name="from"/> is <see langword="null"/>.</para>
276+
/// <para>-or-</para>
277+
/// <para><paramref name="to"/> is <see langword="null"/>.</para>
278+
/// <para>-or-</para>
279+
/// <para><paramref name="subject"/> is <see langword="null"/>.</para>
280+
/// </exception>
234281
public MimeMessage (IEnumerable<InternetAddress> from, IEnumerable<InternetAddress> to, string subject, MimeEntity body) : this ()
235282
{
236283
From.AddRange (from);

UnitTests/MimeMessageTests.cs

+128-3
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ public void TestArgumentExceptions ()
4141
{
4242
var unknown = new Cryptography.UnknownCryptographyContext ();
4343
var message = new MimeMessage ();
44+
var body = new TextPart ("plain") {
45+
Text = "This is the message body."
46+
};
47+
48+
Assert.Throws<ArgumentNullException> (() => new MimeMessage ((IEnumerable<Header>) null));
49+
Assert.Throws<ArgumentNullException> (() => new MimeMessage (null, Array.Empty<InternetAddress> (), string.Empty, body));
50+
Assert.Throws<ArgumentNullException> (() => new MimeMessage (Array.Empty<InternetAddress> (), null, string.Empty, body));
51+
Assert.Throws<ArgumentNullException> (() => new MimeMessage (Array.Empty<InternetAddress> (), Array.Empty<InternetAddress> (), null, body));
4452

4553
Assert.Throws<ArgumentOutOfRangeException> (() => message.Importance = (MessageImportance) 500);
4654
Assert.Throws<ArgumentOutOfRangeException> (() => message.Priority = (MessagePriority) 500);
@@ -95,9 +103,6 @@ public void TestArgumentExceptions ()
95103
var sender = new MailboxAddress ("MimeKit UnitTests", "[email protected]");
96104
message.From.Add (sender);
97105
message.To.Add (new MailboxAddress ("MimeKit UnitTests", "[email protected]"));
98-
var body = new TextPart ("plain") {
99-
Text = "This is the message body."
100-
};
101106

102107
Assert.Throws<ArgumentNullException> (() => message.Sign (null));
103108
Assert.Throws<ArgumentNullException> (() => message.Sign (null, DigestAlgorithm.Sha1));
@@ -835,6 +840,126 @@ public async Task TestReserializationDeliveryStatusReportWithEnsureNewLine ()
835840
}
836841
}
837842

843+
[Test]
844+
public async Task TestReserializationNewFromHeaderList ()
845+
{
846+
string rawRfc822Headers = @"X-Andrew-Authenticated-As: 4099;greenbush.galaxy;Nathaniel Borenstein
847+
Received: from Messages.8.5.N.CUILIB.3.45.SNAP.NOT.LINKED.greenbush.galaxy.sun4.41
848+
via MS.5.6.greenbush.galaxy.sun4_41;
849+
Fri, 12 Jun 1992 13:29:05 -0400 (EDT)
850+
Message-ID : <[email protected]>
851+
Date: Fri, 12 Jun 1992 13:29:05 -0400 (EDT)
852+
From: Nathaniel Borenstein <nsb>
853+
X-Andrew-Message-Size: 152+1
854+
MIME-Version: 1.0
855+
To: Ned Freed <[email protected]>,
856+
[email protected] (Yutaka Sato =?ISO-2022-JP?B?GyRAOjRGI0stGyhK?= )
857+
Subject: MIME & int'l mail
858+
859+
".Replace ("\r\n", "\n");
860+
861+
using (var source = new MemoryStream (Encoding.UTF8.GetBytes (rawRfc822Headers))) {
862+
var headers = HeaderList.Load (source);
863+
var message = new MimeMessage (headers);
864+
865+
Assert.That (message.Date, Is.EqualTo (new DateTimeOffset (1992, 6, 12, 13, 29, 05, TimeSpan.FromHours (-4))), "Date");
866+
Assert.That (message.From.Count, Is.EqualTo (1), "From.Count");
867+
var from = message.From.Mailboxes.First ();
868+
Assert.That (from.Name, Is.EqualTo ("Nathaniel Borenstein"), "From.Name");
869+
Assert.That (from.Address, Is.EqualTo ("nsb"), "From.Address");
870+
Assert.That (message.To.Count, Is.EqualTo (2), "To.Count");
871+
var to = message.To.Mailboxes.ToList ();
872+
Assert.That (to[0].Name, Is.EqualTo ("Ned Freed"), "To[0].Name");
873+
Assert.That (to[0].Address, Is.EqualTo ("[email protected]"), "To[0].Address");
874+
Assert.That (to[1].Name, Is.EqualTo ("Yutaka Sato 佐藤豊"), "To[1].Name");
875+
Assert.That (to[1].Address, Is.EqualTo ("[email protected]"), "To[1].Address");
876+
Assert.That (message.Subject, Is.EqualTo ("MIME & int'l mail"), "Subject");
877+
878+
// Test reserialization of the rfc822 headers
879+
using (var serialized = new MemoryStream ()) {
880+
var options = FormatOptions.Default.Clone ();
881+
options.NewLineFormat = NewLineFormat.Unix;
882+
883+
message.WriteTo (options, serialized);
884+
885+
var result = Encoding.UTF8.GetString (serialized.ToArray ());
886+
887+
Assert.That (result, Is.EqualTo (rawRfc822Headers), "Reserialized message is not identical to the original.");
888+
}
889+
890+
using (var serialized = new MemoryStream ()) {
891+
var options = FormatOptions.Default.Clone ();
892+
options.NewLineFormat = NewLineFormat.Unix;
893+
894+
await message.WriteToAsync (options, serialized);
895+
896+
var result = Encoding.UTF8.GetString (serialized.ToArray ());
897+
898+
Assert.That (result, Is.EqualTo (rawRfc822Headers), "Reserialized message is not identical to the original.");
899+
}
900+
}
901+
}
902+
903+
[Test]
904+
public async Task TestReserializationNewFromIEnumerableHeader ()
905+
{
906+
string rawRfc822Headers = @"X-Andrew-Authenticated-As: 4099;greenbush.galaxy;Nathaniel Borenstein
907+
Received: from Messages.8.5.N.CUILIB.3.45.SNAP.NOT.LINKED.greenbush.galaxy.sun4.41
908+
via MS.5.6.greenbush.galaxy.sun4_41;
909+
Fri, 12 Jun 1992 13:29:05 -0400 (EDT)
910+
Message-ID : <[email protected]>
911+
Date: Fri, 12 Jun 1992 13:29:05 -0400 (EDT)
912+
From: Nathaniel Borenstein <nsb>
913+
X-Andrew-Message-Size: 152+1
914+
MIME-Version: 1.0
915+
To: Ned Freed <[email protected]>,
916+
[email protected] (Yutaka Sato =?ISO-2022-JP?B?GyRAOjRGI0stGyhK?= )
917+
Subject: MIME & int'l mail
918+
919+
".Replace ("\r\n", "\n");
920+
921+
using (var source = new MemoryStream (Encoding.UTF8.GetBytes (rawRfc822Headers))) {
922+
var headers = HeaderList.Load (source).ToList ();
923+
var message = new MimeMessage (headers);
924+
925+
Assert.That (message.Date, Is.EqualTo (new DateTimeOffset (1992, 6, 12, 13, 29, 05, TimeSpan.FromHours (-4))), "Date");
926+
Assert.That (message.From.Count, Is.EqualTo (1), "From.Count");
927+
var from = message.From.Mailboxes.First ();
928+
Assert.That (from.Name, Is.EqualTo ("Nathaniel Borenstein"), "From.Name");
929+
Assert.That (from.Address, Is.EqualTo ("nsb"), "From.Address");
930+
Assert.That (message.To.Count, Is.EqualTo (2), "To.Count");
931+
var to = message.To.Mailboxes.ToList ();
932+
Assert.That (to[0].Name, Is.EqualTo ("Ned Freed"), "To[0].Name");
933+
Assert.That (to[0].Address, Is.EqualTo ("[email protected]"), "To[0].Address");
934+
Assert.That (to[1].Name, Is.EqualTo ("Yutaka Sato 佐藤豊"), "To[1].Name");
935+
Assert.That (to[1].Address, Is.EqualTo ("[email protected]"), "To[1].Address");
936+
Assert.That (message.Subject, Is.EqualTo ("MIME & int'l mail"), "Subject");
937+
938+
// Test reserialization of the rfc822 headers
939+
using (var serialized = new MemoryStream ()) {
940+
var options = FormatOptions.Default.Clone ();
941+
options.NewLineFormat = NewLineFormat.Unix;
942+
943+
message.WriteTo (options, serialized);
944+
945+
var result = Encoding.UTF8.GetString (serialized.ToArray ());
946+
947+
Assert.That (result, Is.EqualTo (rawRfc822Headers), "Reserialized message is not identical to the original.");
948+
}
949+
950+
using (var serialized = new MemoryStream ()) {
951+
var options = FormatOptions.Default.Clone ();
952+
options.NewLineFormat = NewLineFormat.Unix;
953+
954+
await message.WriteToAsync (options, serialized);
955+
956+
var result = Encoding.UTF8.GetString (serialized.ToArray ());
957+
958+
Assert.That (result, Is.EqualTo (rawRfc822Headers), "Reserialized message is not identical to the original.");
959+
}
960+
}
961+
}
962+
838963
[Test]
839964
public void TestMailMessageToMimeMessage ()
840965
{

0 commit comments

Comments
 (0)