Beispiel #1
0
        public static async Task TwoChildrenTest()
        {
            var        stream    = typeof(MimeTests).GetResource("testdata.two-children.eml");
            MimeReader reader    = new MimeReader();
            var        structure = await reader.ReadStructureAsync(stream, CancellationToken.None);

            await TestContent(structure,
                              stream,
                              new ExpectedPart(
                                  new Dictionary <string, string>
            {
                { "From", " From Name <*****@*****.**>" },
                { "To", " To Name<*****@*****.**>" },
                { "Subject", " Sample message" },
                { "MIME-Version", " 1.0" },
                { "Content-Type", " multipart/mixed; boundary=\"simple boundary\"" },
            },
                                  "This is the preamble.  It is to be ignored, though it\r\nis a handy place for mail composers to include an\r\nexplanatory note to non-MIME compliant readers.",
                                  "This is the epilogue.  It is also to be ignored.\r\n",
                                  new ExpectedPart(
                                      new Dictionary <string, string>(),
                                      "This is implicitly typed plain ASCII text.\r\nIt does NOT end with a linebreak."),
                                  new ExpectedPart(
                                      new Dictionary <string, string>
            {
                { "Content-type", " text/plain; charset=us-ascii" },
            },
                                      "This is explicitly typed plain ASCII text.\r\nIt DOES end with a linebreak.\r\n"))
                              );
        }
Beispiel #2
0
        public static async Task Nested()
        {
            var        stream    = typeof(MimeTests).GetResource("testdata.nested.eml");
            MimeReader reader    = new MimeReader();
            var        structure = await reader.ReadStructureAsync(stream, CancellationToken.None);

            await TestContent(structure,
                              stream,
                              new ExpectedPart(
                                  new Dictionary <string, string>
            {
                { "MIME-Version", " 1.0" }, { "From", " Nathaniel Borenstein <*****@*****.**>" },
                { "To", " Ned Freed <*****@*****.**>" }, { "Subject", " A multipart example" },
                { "Content-Type", " multipart/mixed;\r\n     boundary=unique-boundary-1" },
            },
                                  "This is the preamble area of a multipart message.\r\nMail readers that understand multipart format\r\nshould ignore this preamble.\r\nIf you are reading this text, you might want to\r\nconsider changing to a mail reader that understands\r\nhow to properly display multipart messages.",
                                  "",
                                  new ExpectedPart(
                                      new Dictionary <string, string>(),
                                      "\r\n...Some text appears here...\r\n\r\n\r\n[Note that the preceding blank line means\r\nno header fields were given and this is text,\r\nwith charset US ASCII.  It could have been\r\ndone with explicit typing as in the next part.]\r\n"),
                                  new ExpectedPart(new Dictionary <string, string>
            {
                { "Content-type", " text/plain; charset=US-ASCII" },
            },
                                                   "This could have been part of the previous part,\r\nbut illustrates explicit versus implicit\r\ntyping of body parts.\r\n"),
                                  new ExpectedPart(new Dictionary <string, string>
            {
                { "Content-Type", " multipart/parallel;\r\n     boundary=\"unique-\\\"boundary-2\\\"\"" },
            },
                                                   "",
                                                   "",
                                                   new ExpectedPart(new Dictionary <string, string>
            {
                { "Content-Type", " audio/basic" }, { "Content-Transfer-Encoding", " base64" },
            },
                                                                    "\r\n... base64-encoded 8000 Hz single-channel\r\n mu-law-format audio data goes here....\r\n"),
                                                   new ExpectedPart(new Dictionary <string, string>
            {
                { "Content-Type", " image/gif" }, { "Content-Transfer-Encoding", " base64" },
            },
                                                                    "\r\n... base64-encoded image data goes here....\r\n\r\n")
                                                   ),
                                  new ExpectedPart(new Dictionary <string, string>
            {
                { "Content-type", " text/richtext" },
            },
                                                   "This is <bold><italic>richtext.</italic></bold>\r\n<smaller>as defined in RFC 1341</smaller>\r\n<nl><nl>Isn\'t it\r\n<bigger><bigger>cool?</bigger></bigger>\r\n"),
                                  new ExpectedPart(new Dictionary <string, string> {
                { "Content-Type", " message/rfc822" },
            },
                                                   "From: (mailbox in US-ASCII)\r\nTo: (address in US-ASCII)\r\nSubject: (subject in US-ASCII)\r\nContent-Type: Text/plain; charset=ISO-8859-1\r\nContent-Transfer-Encoding: Quoted-printable\r\n\r\n\r\n... Additional text in ISO-8859-1 goes here ...\r\n\r\n")
                                  )
                              );
        }
Beispiel #3
0
        public static async Task SimpleMimeTest()
        {
            var        stream    = typeof(MimeTests).GetResource("testdata.simple.eml");
            MimeReader reader    = new MimeReader();
            var        structure = await reader.ReadStructureAsync(stream, CancellationToken.None);

            await TestContent(structure,
                              stream,
                              new ExpectedPart(
                                  new Dictionary <string, string>
            {
                { "Return-Path", " <*****@*****.**>" },
                { "From", " \"Sender Name\" <*****@*****.**>" },
                { "To", " \"Recipient Name\" <*****@*****.**>,\r\n\t\"Other Name\" <*****@*****.**>" },
                { "Subject", " Sample subject" },
                { "MIME-Version", " 1.0" },
                { "Content-Type", " text/plain;\r\n\tcharset=\"us-ascii\"" },
                { "Content-Transfer-Encoding", " 7bit" },
            },
                                  "Test body\r\n\r\nTest paragraph\r\n"
                                  )
                              );
        }
Beispiel #4
0
        /// <summary>
        /// If "*****@*****.**" is replying to something sent to "*****@*****.**",
        /// replace the "me@example" in the mail
        /// </summary>
        public static async Task <(Stream, string)> ReplaceSenderAsync(
            IDictionary <string, IEnumerable <string> > headers,
            Stream bodyStream,
            string sender,
            CancellationToken token)
        {
            bodyStream.Seek(0, SeekOrigin.Begin);

            if (!headers.TryGetValue("References", out IEnumerable <string> referenes))
            {
                return(bodyStream, sender);
            }

            foreach (var r in referenes)
            {
                Match match = ReferenceOriginalSender.Match(r);
                if (match.Success)
                {
                    var senderParts = sender.Split('@', 2);
                    if (senderParts.Length != 2)
                    {
                        // Not a useful email address...
                        continue;
                    }

                    var headerSender = match.Groups[1].Value;
                    var headerParts  = headerSender.Split('@', 2);
                    if (headerParts.Length != 2)
                    {
                        // Not a useful email address...
                        continue;
                    }

                    if (senderParts[1] != headerParts[1])
                    {
                        // Wrong domain...
                        continue;
                    }

                    if (!headerParts[0].StartsWith(senderParts[0] + "-"))
                    {
                        // Doesn't start with correct extension root
                        continue;
                    }

                    MemoryStream replacedStream = null;
                    try
                    {
                        replacedStream = new MemoryStream();

                        MimeReader reader    = new MimeReader();
                        var        structure = await reader.ReadStructureAsync(bodyStream, token);

                        // Copy the preamble
                        bodyStream.Seek(0, SeekOrigin.Begin);
                        BoundedStream pre = new BoundedStream(bodyStream, structure.HeaderSpan.Start);
                        await pre.CopyToAsync(replacedStream, token);

                        // Replace stuff in headers
                        bodyStream.Seek(structure.HeaderSpan.Start, SeekOrigin.Begin);
                        var headerBytes = await bodyStream.ReadExactlyAsync((int)structure.HeaderSpan.Length, token);

                        string header = Encoding.ASCII.GetString(headerBytes);
                        header = ReplaceFrom.Replace(header, $"$1<{headerSender}>");
                        header = ReplaceReferences.Replace(header,
                                                           m =>
                        {
                            if (String.IsNullOrWhiteSpace(m.Groups["pre"].Value) &&
                                String.IsNullOrWhiteSpace(m.Groups["post"].Value))
                            {
                                // We were the ONLY references header, just remove the whole thing
                                return("");
                            }

                            string space = "";
                            if (!String.IsNullOrEmpty(m.Groups["preSpace"].Value) &&
                                !String.IsNullOrEmpty(m.Groups["postSpace"].Value))
                            {
                                space = m.Groups["preSpace"].Value;
                            }

                            return($"References:{m.Groups["pre"].Value}{space}{m.Groups["post"].Value}");
                        });

                        using (StreamWriter writer = new StreamWriter(replacedStream, Encoding.ASCII, 1024, true))
                        {
                            writer.Write(header);
                        }

                        // Copy message content
                        bodyStream.Seek(structure.HeaderSpan.End, SeekOrigin.Begin);
                        await bodyStream.CopyToAsync(replacedStream, token);

                        bodyStream.Dispose();
                        replacedStream.Seek(0, SeekOrigin.Begin);

                        return(replacedStream, headerSender);
                    }
                    catch
                    {
                        replacedStream?.Dispose();
                        throw;
                    }
                }
            }

            return(bodyStream, sender);
        }