internal override async Task DeserializeOverrideAsync(BoundedStream stream, EventShuttle eventShuttle, CancellationToken cancellationToken) { var rootStream = GetRootStream(stream); var length = GetFieldLength(); Value = length != null ? new Streamlet(rootStream, rootStream.Position, length.ByteCount) : new Streamlet(rootStream, rootStream.Position); if (length != null) { var nullStream = new NullStream(); await stream.CopyToAsync(nullStream, (int)length.ByteCount, CopyToBufferSize, cancellationToken) .ConfigureAwait(false); } else { stream.Seek(0, SeekOrigin.End); } }
/// <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); }