Beispiel #1
0
 public IEnumerable <string> ParseMailboxListHeader(IEnumerable <string> header)
 {
     return(header
            .SelectMany(h => h.SplitQuoted(',', '"', '\\', StringSplitOptions.None))
            .Select(address => MailUtilities.GetMailboxFromAddress(address, _log))
            .Where(m => !string.IsNullOrEmpty(m)));
 }
Beispiel #2
0
        private Task <IWritable[]> CreateDispatchesAsync(
            string mailId,
            IEnumerable <string> recipients,
            string sender,
            CancellationToken token)
        {
            string senderDomain = MailUtilities.GetDomainFromMailbox(sender);

            return(Task.WhenAll(
                       recipients
                       .GroupBy(MailUtilities.GetDomainFromMailbox)
                       .SelectMany(
                           g =>
            {
                if (_settings.Value.DomainName == g.Key)
                {
                    _log.Information($"{mailId} is local mail found");
                    return g.Select(r => _delivery.NewMailAsync(mailId, r, token).Cast <IMailboxItemWriteReference, IWritable>());
                }

                if (_settings.Value.RelayDomains.Any(d => string.Equals(d.Name, g.Key, StringComparison.OrdinalIgnoreCase)) ||
                    _settings.Value.DomainName == senderDomain)
                {
                    _log.Information($"{mailId} is related to {g.Key}");
                    return _transfer.NewMailAsync(mailId, sender, g.ToImmutableList(), token)
                    .Cast <IMailWriteReference, IWritable>()
                    .ToEnumerable();
                }

                _log.Error($"Invalid domain {g.Key}");
                return Enumerable.Empty <Task <IWritable> >();
            }
                           )
                       ));
        }
Beispiel #3
0
        public ISet <string> ExpandDistributionLists(
            string sender,
            IEnumerable <string> originalRecipients,
            HashSet <string> excludedFromExpansion)
        {
            var to = new HashSet <string>();

            foreach (string recipient in originalRecipients)
            {
                DomainSettings domain = null;
                if (_domainSettings.TryGetValue(
                        MailUtilities.GetDomainFromMailbox(recipient),
                        out Lazy <IVolatile <DomainSettings> > settings))
                {
                    domain = settings.Value.Value;
                }

                DistributionList distributionList = domain?.DistributionLists?.FirstOrDefault(dl => dl.Mailbox == recipient);
                if (distributionList != null)
                {
                    if (!CheckValidSender(sender, distributionList))
                    {
                        _log.Warning($"Attempt by invalid sender {sender} to send to DL {distributionList.Mailbox}");
                        continue;
                    }

                    IEnumerable <string> nonExcludedMembers = distributionList.Members.Where(m => !excludedFromExpansion.Contains(m));
                    foreach (string member in nonExcludedMembers)
                    {
                        to.Add(member);
                    }

                    continue;
                }

                {
                    // C# compiler mistake that prevents collapsing the domain.Alias null check
                    if (domain?.Aliases != null && domain.Aliases.TryGetValue(recipient, out string newRecipient))
                    {
                        if (excludedFromExpansion.Contains(newRecipient))
                        {
                            continue;
                        }

                        to.Add(newRecipient);
                        continue;
                    }
                }

                to.Add(recipient);
            }

            return(to);
        }
Beispiel #4
0
        public static bool CheckValidSender(string sender, DistributionList distributionList)
        {
            if (!distributionList.Enabled)
            {
                return(false);
            }

            if (!distributionList.AllowExternalSenders &&
                MailUtilities.GetDomainFromMailbox(sender) != MailUtilities.GetDomainFromMailbox(distributionList.Mailbox))
            {
                return(false);
            }

            return(true);
        }
Beispiel #5
0
        private async Task DispatchSingleMailReferenceAsync(
            IMailReadReference readReference,
            Stream bodyStream,
            CancellationToken token)
        {
            string sender = readReference.Sender;

            IDictionary <string, IEnumerable <string> > headers =
                await MailUtilities.ParseHeadersAsync(bodyStream);

            ISet <string> recipients =
                AugmentRecipients(sender, readReference.Recipients, headers);

            if (!recipients.Any())
            {
                _log.Warning($"{readReference.Id} had no recipients");
            }

            (bodyStream, sender) = await ReplaceSenderAsync(headers, bodyStream, sender, token);

            IWritable[] dispatchReferences = await CreateDispatchesAsync(
                readReference.Id,
                recipients,
                sender,
                token);

            if (!dispatchReferences.Any())
            {
                _log.Warning($"Failed to locate any processor for {readReference.Id}");
            }

            using (var targetStream = new MultiStream(dispatchReferences.Select(r => r.BodyStream)))
            {
                await bodyStream.CopyToAsync(targetStream, token);
            }

            await Task.WhenAll(dispatchReferences.Select(r => r.Store.SaveAsync(r, token)));
        }