Exemple #1
0
        // this method is called from Parallel Invoke, so multiple threads will be executing this concurrently
        private static void SendMailFromUser(SendMailFromUserArgs args)
        {
            var fromMu = args.User;

            // make sure creds are set and setup SMTP client instance for sender to use this session..

            if (!(fromMu.networkCred is NetworkCredential))
            {
                fromMu.networkCred = new NetworkCredential(fromMu.sAMAccountName, args.defaultPassword, DirectoryEntryContext.DefaultDomain);
            }

            using (var curSmtpClient = new SmtpClient(MailUsers.dblist[fromMu.exchangeDBIndex].CurrentServer, 587))
            {
                curSmtpClient.Credentials = fromMu.networkCred;

                var from     = new MailAddress(fromMu.smtpAddress, fromMu.displayName);
                var progress = args.progress;

                var bw            = args.backgroundWorker;
                var dwea          = args.doWorkEventArgs;
                var r             = args.randomInstance;
                var mailBodyStyle = new BodyCompositionRules();

                // only trace here if worker is not being cancelled.  Otherwise if verbose tracing is enabled it can hang UI.
                if (!dwea.Cancel)
                {
                    ts.TraceEvent(TraceEventType.Verbose, 0, "Starting sending mail from {0}", fromMu.displayName);
                }

                foreach (var mal in senderAssignments[fromMu])
                {
                    // check for user cancellation

                    if (bw.CancellationPending)
                    {
                        if (!dwea.Cancel)
                        {
                            dwea.Cancel = true;
                        }

                        Interlocked.CompareExchange(ref progress.cancelled, 1, 0);

                        bw.ReportProgress(0, progress);
                        return;
                    }

                    // check for too many errors

                    if (progress.consecutiveErrorsSending >= maxConsecutiveFailuresSending)
                    {
                        if (!dwea.Cancel)
                        {
                            dwea.Cancel = true;
                        }

                        if (Interlocked.Exchange(ref progress.cancelled, 2) == 0)
                        {
                            //only trace this once, if not already pending cancel
                            ts.TraceEvent(TraceEventType.Critical, 0, "Stopping after {0} consecutive errors", maxConsecutiveFailuresSending);
                        }

                        bw.ReportProgress(0, progress);
                        return;
                    }

                    // compose message

                    var message = new MailMessage(from, mal[0]);
                    if (mal.Count > 1)
                    {
                        for (int i = 1; i < mal.Count; i++)
                        {
                            message.To.Add(mal[i]);
                        }
                    }
                    message.Body    = getRandomBody(r, mailBodyStyle);
                    message.Subject = getRandomSubject(r);

                    // attachments

                    if (r.Next(1, 101) > (100 - args.percentChanceOfAttachments))
                    {
                        message.Attachments.Add(getRandomAttachment(r, mailBodyStyle));
                        if (r.Next(1, 101) > 50) // 50 percent chance of more than one attachment.
                        {
                            var attachments = r.Next(1, args.maxAttachments + 1);

                            for (int i = 1; i < attachments; i++) // start i=1 because we already have 1 attachment
                            {
                                message.Attachments.Add(getRandomAttachment(r, mailBodyStyle));
                            }
                        }
                    }

                    // send

                    try
                    {
                        curSmtpClient.Send(message);
                        Interlocked.Increment(ref progress.messagesSent);
                        Interlocked.Exchange(ref progress.consecutiveErrorsSending, 0);
                    }
                    catch (Exception e)
                    {
                        Interlocked.Increment(ref progress.errorsSending);
                        Interlocked.Increment(ref progress.consecutiveErrorsSending);
                        ts.TraceEvent(TraceEventType.Error, 0, "sending message from user {0}.  {1}", fromMu.displayName, e.ToString());
                    }
                    finally
                    {
                        if (message != null)
                        {
                            message.Dispose();
                        }
                    }


                    bw.ReportProgress(0, progress);
                }

                Interlocked.Increment(ref progress.sendersDone);
                ts.TraceEvent(TraceEventType.Verbose, 0, "Finished sending from {0}", fromMu.displayName);
                bw.ReportProgress(0, progress);
            }
        }
Exemple #2
0
        public static void Mail(GenMailArgs args, object sender, DoWorkEventArgs dwea)
        {
            ts.TraceEvent(TraceEventType.Verbose, 0, "Gen.Mail started.");

            // set connection limit higher
            ServicePointManager.DefaultConnectionLimit = 100;

            ts.TraceEvent(TraceEventType.Information, 0, "Initializing...");
            mailUsers = MailUsers.GetAllOUMailUsers(args.selectedOUPath);
            ts.TraceEvent(TraceEventType.Verbose, 0, "Got list of {0} users.", mailUsers.Count);

            // lower maxadditionalrecips if there are not enough users
            if (mailUsers.Count - 1 < args.maxAdditionalRecips)
            {
                args.maxAdditionalRecips = mailUsers.Count - 1;
            }

            // load and decompress word list if necessary
            if (words == null)
            {
                LoadDictionary();
            }
            ts.TraceEvent(TraceEventType.Information, 0, "Preparing recipient lists...");

            var progress = new GenMailProgress();
            var bw       = sender as BackgroundWorker;

            mailCounter = 0;
            // clear dictionaries in case process was interrupted
            senderAssignments.Clear();
            mailsRemainingForRecipient.Clear();

            // random instance to generate seeds for other random instances
            var rs = new Random();

            // populate mails remaining dictionary

            foreach (GenMailUser mu in mailUsers)
            {
                if (bw.CancellationPending == true)
                {
                    dwea.Cancel = true;
                    return;
                }

                mailsRemainingForRecipient.Add(mu.smtpAddress, args.InitialItems);
            }

            foreach (GenMailUser mu in mailUsers)
            {
                var to = new MailAddress(mu.smtpAddress, mu.displayName);

                while (mailsRemainingForRecipient[mu.smtpAddress] > 0)
                {
                    if (bw.CancellationPending == true)
                    {
                        dwea.Cancel = true;
                        return;
                    }

                    // keep track of # of emails to send for accurate progress later...

                    mailCounter++;

                    // get random user for from address

                    GenMailUser rmu;
                    do
                    {
                        rmu = mailUsers[rs.Next(mailUsers.Count)];
                    }while (rmu == mu && mailUsers.Count > 1);

                    var recipList = new List <MailAddress>()
                    {
                        to
                    };

                    // decrement mail count
                    mailsRemainingForRecipient[mu.smtpAddress]--;

                    // optionally add some random recipients if there are enough people in the mailusers list

                    if (args.maxAdditionalRecips > 0 && rs.Next(1, 101) > (100 - args.percentChanceOfExtraRecips))
                    {
                        // add 1 - configured max
                        var extraRecips = rs.Next(1, args.maxAdditionalRecips + 1);

                        // keep track of additional recips that we don't allow dupes

                        var genMailRecips = new List <GenMailUser>();

                        for (int i = 0; i < extraRecips; i++)
                        {
                            GenMailUser recip;
                            do
                            {
                                recip = mailUsers[rs.Next(mailUsers.Count)];
                            }while (recip == mu || genMailRecips.Contains(recip)); // don't want duplicates

                            if (mailsRemainingForRecipient[recip.smtpAddress] > 0)
                            {
                                recipList.Add(new MailAddress(recip.smtpAddress, recip.displayName));
                                mailsRemainingForRecipient[recip.smtpAddress]--;
                                genMailRecips.Add(recip);
                            }
                        }
                    }

                    if (senderAssignments.ContainsKey(rmu))
                    {
                        senderAssignments[rmu].Add(recipList);
                    }
                    else
                    {
                        var assignments = new List <List <MailAddress> >();
                        assignments.Add(recipList);
                        senderAssignments.Add(rmu, assignments);
                    }
                }
            }
            // free up memory
            mailsRemainingForRecipient.Clear();

            var tasks = senderAssignments.Count;

            progress.numberOfSenders     = tasks;
            progress.numberOfMailboxes   = mailUsers.Count;
            progress.numberOfMailsToSend = mailCounter;


            var actions     = new Action[tasks];
            int actionIndex = 0;

            foreach (var senderGenMailUser in senderAssignments.Keys)
            {
                if (bw.CancellationPending == true)
                {
                    dwea.Cancel = true;
                    return;
                }

                var smfua = new SendMailFromUserArgs();

                smfua.backgroundWorker = bw;
                smfua.doWorkEventArgs  = dwea;

                smfua.progress                   = progress;
                smfua.User                       = senderGenMailUser;
                smfua.randomInstance             = new Random(rs.Next());
                smfua.defaultPassword            = args.DefaultPassword;
                smfua.percentChanceOfAttachments = args.percentChanceOfAttachments;
                smfua.maxAttachments             = args.maxAttachments;


                actions[actionIndex] = () =>
                {
                    SendMailFromUser(smfua);
                };

                actionIndex++;
            }


            ts.TraceEvent(TraceEventType.Information, 0, "Starting send mail threads...");


            if (mailCounter < args.InitialItems * mailUsers.Count)
            {
                ts.TraceEvent(TraceEventType.Information, 0, "Since some items will be received by multiple mailboxes,\n  {0:N0} items per mailbox can be achieved by sending {1:N0} item(s) total.", args.InitialItems, mailCounter);
            }
            var opts = new ParallelOptions();

            //sanity check thread count

            if (args.Threads > 0 && args.Threads <= 100)
            {
                opts.MaxDegreeOfParallelism = args.Threads;
            }
            else
            {
                opts.MaxDegreeOfParallelism = 3;
            }


            // invoke  threads.  This blocks until all complte

            Parallel.Invoke(opts, actions);

            // clear sender assignments

            senderAssignments.Clear();

            if (dwea.Cancel)
            {
                if (progress.cancelled == 2)
                {
                    ts.TraceEvent(TraceEventType.Information, 0, "Mailbox population cancelled due to too many consecutive errors.");
                }
                if (progress.cancelled == 1)
                {
                    ts.TraceEvent(TraceEventType.Information, 0, "Mailbox population cancelled by user.");
                }
            }
            else
            {
                ts.TraceEvent(TraceEventType.Information, 0, "Done sending mail.");
                if (mailCounter < args.InitialItems * mailUsers.Count)
                {
                    ts.TraceEvent(TraceEventType.Information, 0, "Some messages were sent to multiple mailboxes.\n  Sent {0:N0} item(s) total in order for each mailbox to receive {1:N0} item(s).", mailCounter, args.InitialItems);
                }
            }
        }