How to use Mime4Net parser - C# Samples
You can download a file with samples or just look below and review parts of code for making sure that it's really easy to work with Mime4Net component and integrate it in your application.
-
Extracting all message attachments, including attachments inside attached messages
(NI.Mime4Net.Samples.ExtractAttachments)
### Program.cs
using System;
using System.Collections;
using System.Text;
using System.IO;
using NI.Email.Mime.Message;
using NI.Email.Mime.Field;
using NI.Email.Mime.Util;
namespace NI.Mime4Net.Samples.ExtractAttachments {
public class Program {
static void Main(string[] args) {
Stream mimeMsgStream = new MemoryStream( Encoding.ASCII.GetBytes(mimeMsg) );
MimeMessage m = new MimeMessage(mimeMsgStream);
FindAttachments(m);
}
protected static void FindAttachments(Entity mimeEntity) {
if (mimeEntity.IsMultipart)
foreach (Entity part in ((Multipart)mimeEntity.Body).BodyParts) {
ContentTypeField contentType = part.Header.GetField(MimeField.ContentType) as ContentTypeField;
if (contentType==null) continue;
if (part.Body is MimeMessage) {
Console.WriteLine("Attached email found!");
FindAttachments( (MimeMessage)part.Body );
} else if ( !(part.Body is ITextBody) ) {
Console.WriteLine("Attachment found: "+part.Header.GetField(MimeField.ContentType).Raw );
// if available attachment name stored in content type 'name' parameter
// be aware that 'name' _may_ contain invalid file name
string logFile = contentType.Parameters.Contains("name") ?
Path.Combine( Environment.CurrentDirectory, contentType.Parameters["name"].ToString() ) :
Path.Combine( Environment.CurrentDirectory, Path.GetFileNameWithoutExtension(Path.GetTempFileName())+".attachment" );
Console.WriteLine("Writing attachment to file: "+logFile );
FileStream outFile = new FileStream(logFile, FileMode.Create);
BinaryReader rdr = ((IBinaryBody)part.Body).Reader;
byte[] buf = new byte[1024];
int bytesRead = 0;
while ( (bytesRead=rdr.Read(buf,0,buf.Length))>0 )
outFile.Write(buf, 0, bytesRead);
outFile.Flush();
outFile.Close();
}
}
}
static string mimeMsg = @"x-sender: <>
x-receiver: SMS@server07.uk-me.com
Received: from mail.uk-me.com ([192.168.1.1]) by smzmailer.uk-me.com with Microsoft SMTPSVC(6.0.3790.211); Thu, 29 Mar 2007 22:17:11 +0100
Received: from smzmailer.uk-me.com ([192.168.1.17]) by mail.uk-me.com with Microsoft SMTPSVC(5.0.2195.5329); Thu, 29 Mar 2007 22:17:12 +0100
From: postmaster@SMS.uk-me.com
To: sms@uk-me.com
Date: Thu, 29 Mar 2007 22:17:11 +0100
MIME-Version: 1.0
Content-Type: multipart/report; report-type=delivery-status; boundary=""9B095B5ADSN=_01C765779A9125CC00000081smzmailer.uk?me.""
X-DSNContext: 7ce717b1 - 1142 - 00000001 - 00000000
Message-ID:
Subject: Delivery Status Notification (Failure)
Return-Path: <>
X-OriginalArrivalTime: 29 Mar 2007 21:17:12.0222 (UTC) FILETIME=[9DFD5BE0:01C77247]
This is a MIME-formatted message.
Portions of this message may be unreadable without a MIME-capable mail program.
--9B095B5ADSN=_01C765779A9125CC00000081smzmailer.uk?me.
Content-Type: text/plain; charset=unicode-1-1-utf-7
This is an automatically generated Delivery Status Notification.
Delivery to the following recipients failed.
andygriffiths@plc.com
--9B095B5ADSN=_01C765779A9125CC00000081smzmailer.uk?me.
Content-Type: message/delivery-status
Reporting-MTA: dns;smzmailer.uk-me.com
Received-From-MTA: dns;server16
Arrival-Date: Thu, 29 Mar 2007 22:17:07 +0100
Final-Recipient: rfc822;andygriffiths@plc.com
Action: failed
Status: 5.5.0
Diagnostic-Code: smtp;550 Invalid recipient (#5.1.1)
--9B095B5ADSN=_01C765779A9125CC00000081smzmailer.uk?me.
Content-Type: message/rfc822
Received: from server16 ([192.168.1.28]) by smzmailer.uk-me.com with Microsoft SMTPSVC(6.0.3790.211); Thu, 29 Mar 2007 22:17:07 +0100
sensitivity: Normal
reply-to: sup@uk-me.com
importance: Normal
mime-version: 1.0
from: ""Mobile Enterprise SMZ Mailer""
to: michaelaspittles@plc.com, andygriffiths@plc.com, iainhorne@plc.com, markpaver@plc.com
date: 29 Mar 2007 22:17:08 +0100
subject: SMS Analyser Database Update - Vodafone UK(WIN)
content-type: multipart/mixed; boundary=--boundary_6_5c67bd1a-1e7e-4400-af5f-836d043c1017
Return-Path: smsanalyser@uk-me.com
Message-ID:
X-OriginalArrivalTime: 29 Mar 2007 21:17:07.0760 (UTC) FILETIME=[9B548300:01C77247]
----boundary_6_5c67bd1a-1e7e-4400-af5f-836d043c1017
content-type: text/html; charset=utf-8
content-transfer-encoding: base64
PEhUTUw+U01TIEFuYWx5c2lzIFNlcnZpY2UgcG93ZXJlZCBieSBNb2JpbGUgRW50ZXJwcmlz
PlNNUyBBbmFseXNlciBTdXBwb3J0PC9hPiBvciBjYWxsICs0NCAxNjM1IDU2ODc5MDwvSFRNTD4=
----boundary_6_5c67bd1a-1e7e-4400-af5f-836d043c1017
content-type: application/octet-stream; name=WIN_501.smz
content-transfer-encoding: base64
Kk1vYmlsZSBFbnRlcnByaXNlIFNNUyBBbmFseXNlciBTTVogW35TTVp+XVBLAwQUAAsACAAg
ZXJwcmlzZSBTTVMgQW5hbHlzZXIgU01aIEVuZA==
----boundary_6_5c67bd1a-1e7e-4400-af5f-836d043c1017--
--9B095B5ADSN=_01C765779A9125CC00000081smzmailer.uk?me.--";
}
}
-
Simple example how to parse MIME message and generate XML representation of Mime Message (NI.Mime4Net.Samples.ConvertToXml)
### Program.cs
using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Text;
using NI.Email.Mime.Message;
using NI.Email.Mime.Field;
using NI.Email.Mime.Util;
namespace NI.Mime4Net.Samples.ConvertToXml {
public class Program {
static void Main(string[] args) {
Console.WriteLine("MIME Message (if you've downloaded trial version please wait for some time): ");
Stream mimeMsgStream = new MemoryStream( Encoding.ASCII.GetBytes(mimeMsg) );
MimeConverter mimeConverter = new MimeConverter();
MimeMessage m = new MimeMessage(mimeMsgStream);
Console.WriteLine(mimeConverter.ConvertToXml(m));
}
static string mimeMsg = @"Return-Path: eryq@rhine.gsfc.nasa.gov
Sender: john-bigboote
Date: Thu, 11 Apr 1996 01:10:30 -0500
From: Eryq
Organization: Yoyodyne Propulsion Systems
X-Mailer: Mozilla 2.0 (X11; I; Linux 1.1.18 i486)
MIME-Version: 1.0
To: john-bigboote@eryq.pr.mcs.net
Subject: test of double-boundary behavior
Content-Type: multipart/mixed; boundary=""------------299A70B339B65A93542D2AE""
This is a multi-part message in MIME format.
--------------299A70B339B65A93542D2AE
--------------299A70B339B65A93542D2AE
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
Subject: [2] this should be text/html, but double-bound may mess it up
This message contains double boundaries all over the
place. We want to make sure that bad things don't happen.
One bad thing is that the doubled-boundary above can
be mistaken for a single boundary plus a bogus premature
end of headers.
--------------299A70B339B65A93542D2AE
--------------299A70B339B65A93542D2AE
Content-Type: text/html; charset=us-ascii
Subject: [4] this should be text/html, but double-bound may mess it up
Hello? Am I here?
--------------299A70B339B65A93542D2AE
--------------299A70B339B65A93542D2AE
Content-Type: text/html; charset=us-ascii
Subject: [6] this should be text/html, but double-bound may mess it up
Hello? Am I here?
--------------299A70B339B65A93542D2AE
Content-Type: text/html; charset=us-ascii
Subject: [7] this header is improperly terminated
--------------299A70B339B65A93542D2AE
Content-Type: text/html; charset=us-ascii
Subject: [8] this body is empty
--------------299A70B339B65A93542D2AE
Content-Type: text/html; charset=us-ascii
Subject: [9] this body also empty
--------------299A70B339B65A93542D2AE
Content-Type: message/rfc822; name=""/evil/filename"";
From: (mailbox in US-ASCII)
To: (address in US-ASCII)
Subject: [10] an embedded message with broken headers
--------------299A70B339B65A93542D2AE
Content-Type: image/gif; name=""3d-eye.gif""
Content-Transfer-Encoding: base64
Subject: [11] just an image
R0lGODdhKAAoAPMAAAAAAAAAzN3u/76+voiIiG5ubszd7v///+fn5wAAAAAAAAAAAAAAAAAA
AAAAAAAAACwAAAAAKAAoAAAE/hDJSau9eJbMOy4bMoxkaZ5oCkoD6L5wLMfiWns41oZt7lM7
VujnC96IRVsPWQE4nxPjkvmsQmu8oc/KBUSVWk7XepGGLeNrxoxJO1MjILjthg/kWXQ6wO/7
+3dCeRRjfAKHiImJAV+DCF0BiW5VAo1CElaRh5NjlkeYmpyTgpcTAKGiaaSfpwKpVQaxVatL
rU8GaQdOBAQAB7+yXliXTrgAxsW4vFabv8BOtBsBt7cGvwCIT9nOyNEIxuC4zrqKzc9XbODJ
vs7Y5ewH3d7Fxe3jB4rj8t6PuNa6r2bhKQXN17FYCBMqTGiBzSNhx5g0nEMhlsSJjiRYvDjw
E0cdGxQ/gswosoKUkmuU2FnJcsSKGTBjypxJsyaICAA7
--------------299A70B339B65A93542D2AE
Content-Type: message/rfc822; name=""/evil/filename"";
From: (mailbox in US-ASCII)
To: (address in US-ASCII)
Subject: [12] another embedded message with broken headers
--------------299A70B339B65A93542D2AE--";
}
}
### MimeConverter.cs
using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Xml;
using NI.Email.Mime.Message;
using NI.Email.Mime.Field;
using NI.Email.Mime.Util;
namespace NI.Mime4Net.Samples.ConvertToXml {
public class MimeConverter {
public MimeConverter() { }
public string ConvertToXml(MimeMessage msg) {
StringWriter strWr = new StringWriter();
XmlTextWriter xmlWr = new XmlTextWriter(strWr);
xmlWr.Formatting = Formatting.Indented;
GenerateXml(xmlWr, msg, "", "1");
return strWr.ToString();
}
protected void GenerateXml(XmlWriter xmlWr, Entity e, String prefix, String id) {
if (e is MimeMessage) {
xmlWr.WriteStartElement("message");
} else {
xmlWr.WriteStartElement("body-part");
}
xmlWr.WriteStartElement("header");
foreach (MimeField fld in e.Header.Fields) {
xmlWr.WriteElementString("field", fld.Raw );
}
xmlWr.WriteEndElement();
if (e.Body is Multipart) {
xmlWr.WriteStartElement("multipart");
Multipart multipart =(Multipart) e.Body;
IList parts =multipart.BodyParts;
xmlWr.WriteElementString("preamble", multipart.Preamble);
for (int i=0; i < parts.Count; i++) {
GenerateXml(xmlWr, (Entity)parts[i], prefix, id + "_" + (i+1).ToString() );
}
xmlWr.WriteElementString("epilogue", multipart.Epilogue);
xmlWr.WriteEndElement();
} else if (e.Body is MimeMessage) {
GenerateXml(xmlWr, (MimeMessage) e.Body, prefix, id + "_1");
} else {
IBody b = e.Body;
String name = prefix + "_decoded_" + id
+ (b is ITextBody ? ".txt" : ".bin");
String tag = b is ITextBody ? "text-body" : "binary-body";
xmlWr.WriteStartElement(tag);
xmlWr.WriteAttributeString("name", name);
xmlWr.WriteEndElement();
}
xmlWr.WriteEndElement();
}
}
}
-
A sample application showing how Mime4Net can be used for composing messages with MHTML (NI.Mime4Net.Samples.ComposeMhtml)
using System;
using System.Collections;
using System.Text;
using System.IO;
using NI.Email.Mime.Message;
using NI.Email.Mime.Field;
using NI.Email.Mime.Util;
namespace NI.Mime4Net.Samples.ComposeMhtml {
public class Program {
static void Main(string[] args) {
Multipart multi = new Multipart();
// text part
BodyPart bodyFirst = new BodyPart();
Header bodyFirstHeader = new Header();
bodyFirstHeader.AddField(MimeField.Parse(@"Content-Type: text/html; charset=""US-ASCII"""));
bodyFirstHeader.AddField(MimeField.Parse(@"Content-ID: "));
bodyFirst.Header = bodyFirstHeader;
bodyFirst.Body = new MemoryTextBody(new MemoryStream(Encoding.ASCII.GetBytes(
@"Sample HTML body: <img src=""cid:image_part@mhtmltest.mime4net"" alt=""MIME4Net"" border=""0"">")));
multi.AddBodyPart(bodyFirst);
// m4n logo part
Stream logoImgStream = typeof(Program).Assembly.GetManifestResourceStream("NI.Mime4Net.Samples.ComposeMhtml.logo.gif" );
multi.AddRelatedBinaryPart(logoImgStream, "image_part@mhtmltest.mime4net", "image/gif", "mhtml_test_m4nlogo.gif");
//composing main msg
MimeMessage msg = new MimeMessage();
Header msgHeader = new Header();
msgHeader.AddField(MimeField.Parse(@"From: from@mime4.net"));
msgHeader.AddField(MimeField.Parse(@"To: to@mime4.net"));
msgHeader.AddField(MimeField.Parse(@"Subject: MHTML sample"));
msgHeader.AddField(MimeField.Parse(@"Mime-Version: 1.0"));
string ctype = "Content-Type: multipart/related; boundary=";
ctype += @"MY_BOUNDARY;";
ctype += @" type=""text/html"";";
ctype += @" start=""""";
msgHeader.AddField(MimeField.Parse(ctype));
msg.Header = msgHeader;
msg.Body = multi;
MemoryStream memStream = new MemoryStream();
msg.WriteTo( memStream );
Console.WriteLine( Encoding.ASCII.GetString(memStream.ToArray()) );
}
}
}
-
Parsing infinite MIME streams with Mime4Net
(NI.Mime4Net.Samples.InfiniteMimeStream)
### Program.cs
using System;
using System.Collections;
using System.Text;
using NI.Email.Mime;
using NI.Email.Mime.Decoder;
using NI.Email.Mime.Message;
namespace NI.Mime4Net.Samples.InfiniteMimeStream {
class Program {
static void Main(string[] args) {
string startMimePart = @"Content-type: multipart/x-mixed-replace;boundary=---ThisRandomString---
-----ThisRandomString---
";
string infiniteMimePart = @"Content-type: text/html
This part updates every 2 seconds
-----ThisRandomString---
";
DelayedMemoryStream inputStream = new DelayedMemoryStream(
Encoding.ASCII.GetBytes(startMimePart), Encoding.ASCII.GetBytes(infiniteMimePart) );
MimeStreamParser mimeStreamParser = new MimeStreamParser();
mimeStreamParser.SetContentHandler( new MimePartHandler() );
mimeStreamParser.Parse(inputStream);
}
class MimePartHandler : IContentHandler {
public void Body(BodyDescriptor bd, System.IO.Stream inputStream) {
// skip multipart
if (bd.IsMultipart) return;
Console.WriteLine("Received new part, content type: "+bd.MimeType);
string enc = bd.TransferEncoding;
if ("base64".Equals(enc)) {
inputStream = new Base64InputStream(inputStream);
} else if ("quoted-printable".Equals(enc)) {
inputStream = new QuotedPrintableInputStream(inputStream);
}
if (bd.MimeType.StartsWith("text/")) {
MemoryTextBody body = new MemoryTextBody(inputStream, bd.Charset);
Console.WriteLine( body.Reader.ReadToEnd() );
}
}
public void EndBodyPart() { }
public void EndHeader() { }
public void EndMessage() { }
public void EndMultipart() { }
public void Epilogue(System.IO.Stream inputStream) { }
public void Field(string fieldData) { }
public void Preamble(System.IO.Stream inputStream) { }
public void Raw(System.IO.Stream inputStream) { }
public void StartBodyPart() { }
public void StartHeader() { }
public void StartMessage() { }
public void StartMultipart(BodyDescriptor bd) { }
}
}
}
### DelayedMemoryStream.cs
using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Threading;
namespace NI.Mime4Net.Samples.InfiniteMimeStream {
public class DelayedMemoryStream : Stream {
MemoryStream RepeatStream;
byte[] RepeatBuffer;
public DelayedMemoryStream(byte[] startBuffer, byte[] repeatBuffer) {
RepeatStream = new MemoryStream(startBuffer);
RepeatBuffer = repeatBuffer;
}
public override int ReadByte() {
int b = RepeatStream.ReadByte();
if (b==-1) {
Thread.Sleep(2000); // 2 secs
RepeatStream = new MemoryStream(RepeatBuffer);
b = RepeatStream.ReadByte();
}
return b;
}
public override bool CanRead {
get { return RepeatStream.CanRead; }
}
public override bool CanSeek {
get { return RepeatStream.CanSeek; }
}
public override bool CanWrite {
get { return RepeatStream.CanWrite; }
}
public override void Flush() {
RepeatStream.Flush();
}
public override long Length {
get { return RepeatStream.Length; }
}
public override long Position {
get { return RepeatStream.Position; }
set { RepeatStream.Position = value; }
}
public override int Read(byte[] buffer, int offset, int count) {
return RepeatStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin) {
return RepeatStream.Seek(offset, origin);
}
public override void SetLength(long value) {
RepeatStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count) {
RepeatStream.Write(buffer, offset, count);
}
}
}
These samples should not be considered commercial quality applications. They are just intended to illustrate how to use some particular feature, or group of features in Mime4Net. Feel free to polish them into applications of your own, or extract
sections to use in your own code.
|