Example #1
0
        public void ShouldShallowCloneContext()
        {
            var options = new UnsubscribeOptions();

            options.Context.Set("someKey", "someValue");

            var testee = new UnsubscribeContext(new RootContext(null, null, null), typeof(object), options);

            testee.Extensions.Set("someKey", "updatedValue");
            testee.Extensions.Set("anotherKey", "anotherValue");

            string value;
            string anotherValue;

            options.Context.TryGet("someKey", out value);
            Assert.AreEqual("someValue", value);
            Assert.IsFalse(options.Context.TryGet("anotherKey", out anotherValue));
            string updatedValue;
            string anotherValue2;

            testee.Extensions.TryGet("someKey", out updatedValue);
            testee.Extensions.TryGet("anotherKey", out anotherValue2);
            Assert.AreEqual("updatedValue", updatedValue);
            Assert.AreEqual("anotherValue", anotherValue2);
        }
Example #2
0
        /// <summary>
        /// Send an email to a single recipient using a dynamic template.
        /// </summary>
        /// <param name="to">To.</param>
        /// <param name="from">From.</param>
        /// <param name="dynamicTemplateId">The identifier of the template.</param>
        /// <param name="dynamicData">The data to be merged in the content.</param>
        /// <param name="trackOpens">if set to <c>true</c> [track opens].</param>
        /// <param name="trackClicks">if set to <c>true</c> [track clicks].</param>
        /// <param name="subscriptionTracking">The subscription tracking.</param>
        /// <param name="replyTo">The reply to.</param>
        /// <param name="attachments">The attachments.</param>
        /// <param name="sections">The sections.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="customArgs">The custom arguments.</param>
        /// <param name="sendAt">The send at.</param>
        /// <param name="batchId">The batch identifier.</param>
        /// <param name="unsubscribeOptions">The unsubscribe options.</param>
        /// <param name="mailSettings">The mail settings.</param>
        /// <param name="priority">The priority.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The result.
        /// </returns>
        /// <remarks>
        /// This is a convenience method with simplified parameters.
        /// If you need more options, use the <see cref="SendAsync" /> method.
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException">Too many recipients.</exception>
        /// <exception cref="Exception">Email exceeds the size limit.</exception>
        public Task <WarmupResult> SendToSingleRecipientAsync(
            MailAddress to,
            MailAddress from,
            string dynamicTemplateId,
            object dynamicData = null,
            bool trackOpens    = true,
            bool trackClicks   = true,
            SubscriptionTrackingSettings subscriptionTracking = null,
            MailAddress replyTo = null,
            IEnumerable <Attachment> attachments = null,
            IEnumerable <KeyValuePair <string, string> > sections = null,
            IEnumerable <KeyValuePair <string, string> > headers  = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            MailSettings mailSettings             = null,
            MailPriority priority = MailPriority.Normal,
            CancellationToken cancellationToken = default)
        {
            var recipients = new[] { to };

            return(SendToMultipleRecipientsAsync(recipients, from, dynamicTemplateId, dynamicData, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, mailSettings, priority, cancellationToken));
        }
Example #3
0
        /// <summary>
        /// Send the same email to multiple recipients without using a template (which means you must provide the subject, html content and text content).
        /// </summary>
        /// <param name="recipients">The recipients.</param>
        /// <param name="from">From.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="htmlContent">Content of the HTML.</param>
        /// <param name="textContent">Content of the text.</param>
        /// <param name="trackOpens">if set to <c>true</c> [track opens].</param>
        /// <param name="trackClicks">if set to <c>true</c> [track clicks].</param>
        /// <param name="subscriptionTracking">The subscription tracking.</param>
        /// <param name="replyTo">The reply to.</param>
        /// <param name="attachments">The attachments.</param>
        /// <param name="sections">The sections.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="customArgs">The custom arguments.</param>
        /// <param name="sendAt">The send at.</param>
        /// <param name="batchId">The batch identifier.</param>
        /// <param name="unsubscribeOptions">The unsubscribe options.</param>
        /// <param name="ipPoolName">Name of the ip pool.</param>
        /// <param name="mailSettings">The mail settings.</param>
        /// <param name="priority">The priority.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The message id.
        /// </returns>
        /// <remarks>
        /// This is a convenience method with simplified parameters.
        /// If you need more options, use the <see cref="SendAsync" /> method.
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException">Too many recipients.</exception>
        /// <exception cref="Exception">Email exceeds the size limit.</exception>
        public Task <string> SendToMultipleRecipientsAsync(
            IEnumerable <MailAddress> recipients,
            MailAddress from,
            string subject,
            string htmlContent,
            string textContent,
            bool trackOpens  = true,
            bool trackClicks = true,
            SubscriptionTrackingSettings subscriptionTracking = null,
            MailAddress replyTo = null,
            IEnumerable <Attachment> attachments = null,
            IEnumerable <KeyValuePair <string, string> > sections = null,
            IEnumerable <KeyValuePair <string, string> > headers  = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            MailPriority priority               = MailPriority.Normal,
            CancellationToken cancellationToken = default)
        {
            var personalizations = new[]
            {
                new MailPersonalization
                {
                    To = recipients.ToArray()
                }
            };

            var contents = new List <MailContent>();

            if (!string.IsNullOrEmpty(textContent))
            {
                contents.Add(new MailContent("text/plain", textContent));
            }
            if (!string.IsNullOrEmpty(htmlContent))
            {
                contents.Add(new MailContent("text/html", htmlContent));
            }

            var trackingSettings = new TrackingSettings
            {
                ClickTracking = new ClickTrackingSettings
                {
                    EnabledInHtmlContent = trackClicks,
                    EnabledInTextContent = trackClicks
                },
                OpenTracking = new OpenTrackingSettings {
                    Enabled = trackOpens
                },
                GoogleAnalytics = new GoogleAnalyticsSettings {
                    Enabled = false
                },
                SubscriptionTracking = subscriptionTracking
            };

            return(SendAsync(personalizations, subject, contents, from, replyTo, attachments, null, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken));
        }
Example #4
0
        /// <summary>
        /// Send an email to a single recipient
        /// </summary>
        /// <param name="to">To.</param>
        /// <param name="from">From.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="htmlContent">Content of the HTML.</param>
        /// <param name="textContent">Content of the text.</param>
        /// <param name="trackOpens">if set to <c>true</c> [track opens].</param>
        /// <param name="trackClicks">if set to <c>true</c> [track clicks].</param>
        /// <param name="subscriptionTracking">The subscription tracking.</param>
        /// <param name="replyTo">The reply to.</param>
        /// <param name="attachments">The attachments.</param>
        /// <param name="templateId">The template identifier.</param>
        /// <param name="sections">The sections.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="customArgs">The custom arguments.</param>
        /// <param name="sendAt">The send at.</param>
        /// <param name="batchId">The batch identifier.</param>
        /// <param name="unsubscribeOptions">The unsubscribe options.</param>
        /// <param name="ipPoolName">Name of the ip pool.</param>
        /// <param name="mailSettings">The mail settings.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The message id.
        /// </returns>
        /// <remarks>
        /// This is a convenience method with simplified parameters.
        /// If you need more options, use the <see cref="SendAsync" /> method.
        /// </remarks>
        /// <exception cref="Exception">Email exceeds the size limit</exception>
        public Task <string> SendToSingleRecipientAsync(
            MailAddress to,
            MailAddress from,
            string subject,
            string htmlContent,
            string textContent,
            bool trackOpens  = true,
            bool trackClicks = true,
            SubscriptionTrackingSettings subscriptionTracking = null,
            MailAddress replyTo = null,
            IEnumerable <Attachment> attachments = null,
            string templateId = null,
            IEnumerable <KeyValuePair <string, string> > sections = null,
            IEnumerable <KeyValuePair <string, string> > headers  = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var recipients = new[] { to };

            return(SendToMultipleRecipientsAsync(recipients, from, subject, htmlContent, textContent, trackOpens, trackClicks, subscriptionTracking, replyTo, attachments, templateId, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, cancellationToken));
        }
Example #5
0
        /// <summary>
        /// Unsubscribe a newline-separated list of addresses.
        /// </summary>
        /// <param name="addresses"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public async Task <UnsubscribeResult> UnsubscribeAsync(string addresses, UnsubscribeOptions options = UnsubscribeOptions.None)
        {
            var result = new UnsubscribeResult();

            if (!String.IsNullOrWhiteSpace(addresses))
            {
                var req = new RestRequest(Method.POST);
                req.AddParameter("unsubscribees", addresses);
                req.AddParameter("send_unsub_ack_to_this_batch", options.HasFlag(UnsubscribeOptions.SendAcknowledgement).ToInt());
                req.AddParameter("send_unsub_notifications_to_list_owner", options.HasFlag(UnsubscribeOptions.NotifyOwner).ToInt());

                var resp = await this.GetClient().ExecuteAdminRequestAsync(_removePage, req).ConfigureAwait(false);

                var doc = resp.Content.GetHtmlDocument();

                string xpath = "//h5[contains(translate(text(), 'SU', 'su'), 'successfully unsubscribed')]/following-sibling::ul[1]/li";
                foreach (var node in doc.DocumentNode.SafeSelectNodes(xpath))
                {
                    result.Unsubscribed.Add(node.InnerText.Trim());
                }

                xpath = "//h3[descendant::*[contains(translate(text(), 'CU', 'cu'), 'cannot unsubscribe')]]/following-sibling::ul[1]/li";
                foreach (var node in doc.DocumentNode.SafeSelectNodes(xpath))
                {
                    result.NonMembers.Add(node.InnerText.Trim());
                }

                if (_emailListPopulated)
                {
                    await PopulateEmailListAsync().ConfigureAwait(false);
                }
            }

            return(result);
        }
Example #6
0
        public async Task Unsubscribe(Type eventType, UnsubscribeOptions options, ExecutionContext executionContext, ILogger functionsLogger = null, CancellationToken cancellationToken = default)
        {
            FunctionsLoggerFactory.Instance.SetCurrentLogger(functionsLogger);

            await InitializeEndpointIfNecessary(executionContext, functionsLogger, cancellationToken).ConfigureAwait(false);

            await endpoint.Unsubscribe(eventType, options, cancellationToken).ConfigureAwait(false);
        }
        public Task Unsubscribe(Type eventType, UnsubscribeOptions unsubscribeOptions)
        {
            Guard.AgainstNull(nameof(eventType), eventType);
            Guard.AgainstNull(nameof(unsubscribeOptions), unsubscribeOptions);

            GuardAgainstUseWhenNotStarted();
            return(messageSession.Unsubscribe(eventType, unsubscribeOptions));
        }
        public Task Unsubscribe(Type eventType, UnsubscribeOptions unsubscribeOptions, CancellationToken cancellationToken = default)
        {
            Guard.AgainstNull(nameof(eventType), eventType);
            Guard.AgainstNull(nameof(unsubscribeOptions), unsubscribeOptions);

            GuardAgainstUseWhenNotStarted();
            return(messageSession.Unsubscribe(eventType, unsubscribeOptions, cancellationToken));
        }
Example #9
0
        /// <summary>
        /// Unsubscribe all members.
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public async Task <UnsubscribeResult> UnsubscribeAllAsync(UnsubscribeOptions options = UnsubscribeOptions.None)
        {
            if (!_emailListPopulated)
            {
                await PopulateEmailListAsync().ConfigureAwait(false);
            }

            return(await UnsubscribeAsync(EmailList, options).ConfigureAwait(false));
        }
Example #10
0
        public static Task Unsubscribe(IBehaviorContext context, Type eventType, UnsubscribeOptions options)
        {
            var unsubscribeContext = new UnsubscribeContext(
                context,
                eventType,
                options.Context);

            return(unsubscribeContext.InvokePipeline <IUnsubscribeContext>());
        }
        public void Unsubscribe_ShouldTrackUnsubscriptions()
        {
            var session = new TestableMessageSession();
            var options = new UnsubscribeOptions();

            session.Unsubscribe(typeof(MyEvent), options);

            Assert.AreEqual(1, session.Unsubscription.Length);
            Assert.AreSame(options, session.Unsubscription[0].Options);
            Assert.AreEqual(typeof(MyEvent), session.Unsubscription[0].Message);
        }
Example #12
0
        /// <summary>
        /// Send the same email to multiple recipients.
        /// </summary>
        /// <param name="recipients">The recipients.</param>
        /// <param name="from">From.</param>
        /// <param name="dynamicTemplateId">The identifier of the template.</param>
        /// <param name="dynamicData">The data to be merged in the content.</param>
        /// <param name="trackOpens">if set to <c>true</c> [track opens].</param>
        /// <param name="trackClicks">if set to <c>true</c> [track clicks].</param>
        /// <param name="subscriptionTracking">The subscription tracking.</param>
        /// <param name="replyTo">The reply to.</param>
        /// <param name="attachments">The attachments.</param>
        /// <param name="sections">The sections.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="customArgs">The custom arguments.</param>
        /// <param name="sendAt">The send at.</param>
        /// <param name="batchId">The batch identifier.</param>
        /// <param name="unsubscribeOptions">The unsubscribe options.</param>
        /// <param name="ipPoolName">Name of the ip pool.</param>
        /// <param name="mailSettings">The mail settings.</param>
        /// <param name="priority">The priority.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The message id.
        /// </returns>
        /// <remarks>
        /// This is a convenience method with simplified parameters.
        /// If you need more options, use the <see cref="SendAsync" /> method.
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException">Too many recipients.</exception>
        /// <exception cref="Exception">Email exceeds the size limit.</exception>
        public Task <string> SendToMultipleRecipientsAsync(
            IEnumerable <MailAddress> recipients,
            MailAddress from,
            string dynamicTemplateId,
            object dynamicData = null,
            bool trackOpens    = true,
            bool trackClicks   = true,
            SubscriptionTrackingSettings subscriptionTracking = null,
            MailAddress replyTo = null,
            IEnumerable <Attachment> attachments = null,
            IEnumerable <KeyValuePair <string, string> > sections = null,
            IEnumerable <KeyValuePair <string, string> > headers  = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            MailPriority priority               = MailPriority.Normal,
            CancellationToken cancellationToken = default)
        {
            if (!Template.IsDynamic(dynamicTemplateId))
            {
                throw new ArgumentException($"{dynamicTemplateId} is not a valid dynamic template identifier.", nameof(dynamicTemplateId));
            }

            var personalizations = new[]
            {
                new MailPersonalization
                {
                    To          = recipients.ToArray(),
                    DynamicData = dynamicData
                }
            };

            var trackingSettings = new TrackingSettings
            {
                ClickTracking = new ClickTrackingSettings
                {
                    EnabledInHtmlContent = trackClicks,
                    EnabledInTextContent = trackClicks
                },
                OpenTracking = new OpenTrackingSettings {
                    Enabled = trackOpens
                },
                GoogleAnalytics = new GoogleAnalyticsSettings {
                    Enabled = false
                },
                SubscriptionTracking = subscriptionTracking
            };

            return(SendAsync(personalizations, null, null, from, replyTo, attachments, dynamicTemplateId, sections, headers, categories, customArgs, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, priority, cancellationToken));
        }
Example #13
0
        public Task Unsubscribe(IBehaviorContext context, Type eventType, UnsubscribeOptions options)
        {
            var unsubscribeContext = new UnsubscribeContext(
                context,
                eventType,
                options.Context);

            MergeDispatchProperties(unsubscribeContext, options.DispatchProperties);

            return(unsubscribePipeline.Invoke(unsubscribeContext));
        }
Example #14
0
        public void Unsubscribe_ShouldTrackUnsubscriptions()
        {
            var session = new TestableMessageSession();
            var options = new UnsubscribeOptions();

            session.Unsubscribe(typeof(MyEvent), options);

            Assert.AreEqual(1, session.Unsubscription.Length);
            Assert.AreSame(options, session.Unsubscription[0].Options);
            Assert.AreEqual(typeof(MyEvent), session.Unsubscription[0].Message);
        }
Example #15
0
        public async System.Threading.Tasks.Task Unsubscribe_ShouldTrackUnsubscriptionsAsync()
        {
            var session = new TestableMessageSession();
            var options = new UnsubscribeOptions();

            await session.Unsubscribe(typeof(MyEvent), options);

            Assert.AreEqual(1, session.Unsubscription.Length);
            Assert.AreSame(options, session.Unsubscription[0].Options);
            Assert.AreEqual(typeof(MyEvent), session.Unsubscription[0].Message);
        }
        public UnsubscribeContext(IBehaviorContext parentContext, Type eventType, UnsubscribeOptions options)
            : base(parentContext)
        {
            Guard.AgainstNull(nameof(parentContext), parentContext);
            Guard.AgainstNull(nameof(eventType), eventType);
            Guard.AgainstNull(nameof(options), options);

            parentContext.Extensions.Merge(options.Context);

            EventType = eventType;
        }
        public UnsubscribeContext(IBehaviorContext parentContext, Type eventType, UnsubscribeOptions options)
            : base(parentContext)
        {
            Guard.AgainstNull(nameof(parentContext), parentContext);
            Guard.AgainstNull(nameof(eventType), eventType);
            Guard.AgainstNull(nameof(options), options);

            Merge(options.Context);

            EventType = eventType;
        }
Example #18
0
        public async Task Unsubscribe_Sends_Right_Params(UnsubscribeOptions options)
        {
            await _list.Membership.UnsubscribeAsync("foo", options);

            var ack   = options.HasFlag(UnsubscribeOptions.SendAcknowledgement);
            var owner = options.HasFlag(UnsubscribeOptions.NotifyOwner);

            _request.Should().NotBeNull();
            _parmStrings.Should().Contain("unsubscribees=foo");
            _parmStrings.Should().Contain($"send_unsub_ack_to_this_batch={ack.ToInt()}");
            _parmStrings.Should().Contain($"send_unsub_notifications_to_list_owner={owner.ToInt()}");
        }
Example #19
0
        public static Task Unsubscribe(IBehaviorContext context, Type eventType, UnsubscribeOptions options)
        {
            var cache    = context.Extensions.Get <IPipelineCache>();
            var pipeline = cache.Pipeline <IUnsubscribeContext>();

            var subscribeContext = new UnsubscribeContext(
                context,
                eventType,
                options.Context);

            return(pipeline.Invoke(subscribeContext));
        }
Example #20
0
        public static Task Unsubscribe(IBehaviorContext context, Type eventType, UnsubscribeOptions options)
        {
            var settings = context.Builder.Build <ReadOnlySettings>();
            var pipeline = new PipelineBase <IUnsubscribeContext>(context.Builder, settings, settings.Get <PipelineConfiguration>().MainPipeline);

            var subscribeContext = new UnsubscribeContext(
                context,
                eventType,
                options);

            return(pipeline.Invoke(subscribeContext));
        }
Example #21
0
        public void ShouldNotMergeOptionsToParentContext()
        {
            var options = new UnsubscribeOptions();

            options.Context.Set("someKey", "someValue");

            var parentContext = new RootContext(null, null, null);

            new UnsubscribeContext(parentContext, typeof(object), options);

            string parentContextValue;
            var    valueFound = parentContext.TryGet("someKey", out parentContextValue);

            Assert.IsFalse(valueFound);
        }
    public async Task MessageSession()
    {
        var context          = new TestableMessageSession();
        var subscribeOptions = new SubscribeOptions();

        subscribeOptions.RequireImmediateDispatch();
        await context.Subscribe(typeof(MyMessage), subscribeOptions);

        var unsubscribeOptions = new UnsubscribeOptions();

        unsubscribeOptions.RequireImmediateDispatch();
        await context.Unsubscribe(typeof(MyMessage), unsubscribeOptions);

        await Verify(context);
    }
Example #23
0
        /// <summary>
        /// Send the same email to multiple recipients
        /// </summary>
        /// <remarks>
        /// This is a convenience method with simplified parameters.
        /// If you need more options, use the <see cref="SendAsync"/> method.
        /// </remarks>
        public Task SendToMultipleRecipientsAsync(
            IEnumerable <MailAddress> recipients,
            MailAddress from,
            string subject,
            string htmlContent,
            string textContent,
            bool trackOpens  = true,
            bool trackClicks = true,
            SubscriptionTrackingSettings subscriptionTracking = null,
            MailAddress replyTo = null,
            IEnumerable <Attachment> attachments = null,
            string templateId = null,
            IEnumerable <KeyValuePair <string, string> > sections = null,
            IEnumerable <KeyValuePair <string, string> > headers  = null,
            IEnumerable <string> categories = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var personalizations = recipients.Select(r => new MailPersonalization {
                To = new[] { r }
            });
            var contents = new[]
            {
                new MailContent("text/plain", textContent),
                new MailContent("text/html", htmlContent)
            };
            var trackingSettings = new TrackingSettings
            {
                ClickTracking = new ClickTrackingSettings
                {
                    Enabled = trackClicks,
                    EnabledInTextContent = trackClicks
                },
                OpenTracking = new OpenTrackingSettings {
                    Enabled = trackOpens
                },
                GoogleAnalytics = new GoogleAnalyticsSettings {
                    Enabled = false
                },
                SubscriptionTracking = subscriptionTracking
            };

            return(SendAsync(personalizations, subject, contents, from, replyTo, attachments, templateId, sections, headers, categories, sendAt, batchId, unsubscribeOptions, ipPoolName, mailSettings, trackingSettings, cancellationToken));
        }
Example #24
0
        private Task <string> SendEmailAsync(
            IEnumerable <MailPersonalization> personalizations,
            string subject,
            IEnumerable <MailContent> contents,
            MailAddress from,
            MailAddress replyTo = null,
            IEnumerable <Attachment> attachments = null,
            string templateId = null,
            IEnumerable <KeyValuePair <string, string> > sections = null,
            IEnumerable <KeyValuePair <string, string> > headers  = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            TrackingSettings trackingSettings   = null,
            MailPriority priority               = MailPriority.Normal,
            CancellationToken cancellationToken = default)
        {
            if (personalizations == null || !personalizations.Any())
            {
                return(Task.FromResult <string>(null));
            }

            return(_client.Mail
                   .SendAsync(
                       personalizations,
                       subject,
                       contents,
                       from,
                       replyTo,
                       attachments,
                       templateId,
                       sections,
                       headers,
                       categories,
                       customArgs,
                       sendAt,
                       batchId,
                       unsubscribeOptions,
                       ipPoolName,
                       mailSettings,
                       trackingSettings,
                       priority,
                       cancellationToken));
        }
        public async Task Should_Dispatch_according_to_max_retries_when_dispatch_fails()
        {
            var options = new UnsubscribeOptions();
            var state = options.GetExtensions().GetOrCreate<MessageDrivenUnsubscribeTerminator.Settings>();
            state.MaxRetries = 10;
            state.RetryDelay = TimeSpan.Zero;
            dispatcher.FailDispatch(10);

            var context = new TestableUnsubscribeContext
            {
                Extensions = options.Context
            };

            await terminator.Invoke(context, c => TaskEx.CompletedTask);

            Assert.AreEqual(1, dispatcher.DispatchedTransportOperations.Count);
            Assert.AreEqual(10, dispatcher.FailedNumberOfTimes);
        }
        public void Should_Throw_when_max_retries_reached()
        {
            var options = new UnsubscribeOptions();
            var state = options.GetExtensions().GetOrCreate<MessageDrivenUnsubscribeTerminator.Settings>();
            state.MaxRetries = 10;
            state.RetryDelay = TimeSpan.Zero;
            dispatcher.FailDispatch(11);

            var context = new TestableUnsubscribeContext
            {
                Extensions = options.Context
            };

            Assert.That(async () => await terminator.Invoke(context, c => TaskEx.CompletedTask), Throws.InstanceOf<QueueNotFoundException>());

            Assert.AreEqual(0, dispatcher.DispatchedTransportOperations.Count);
            Assert.AreEqual(11, dispatcher.FailedNumberOfTimes);
        }
Example #27
0
        public async Task Should_Dispatch_according_to_max_retries_when_dispatch_fails()
        {
            var options = new UnsubscribeOptions();
            var state   = options.GetExtensions().GetOrCreate <MessageDrivenUnsubscribeTerminator.Settings>();

            state.MaxRetries = 10;
            state.RetryDelay = TimeSpan.Zero;
            dispatcher.FailDispatch(10);

            var context = new TestableUnsubscribeContext
            {
                Extensions = options.Context
            };

            await terminator.Invoke(context, c => Task.CompletedTask);

            Assert.AreEqual(1, dispatcher.DispatchedTransportOperations.Count);
            Assert.AreEqual(10, dispatcher.FailedNumberOfTimes);
        }
Example #28
0
        public void Should_Throw_when_max_retries_reached()
        {
            var options = new UnsubscribeOptions();
            var state   = options.GetExtensions().GetOrCreate <MessageDrivenUnsubscribeTerminator.Settings>();

            state.MaxRetries = 10;
            state.RetryDelay = TimeSpan.Zero;
            dispatcher.FailDispatch(11);

            var context = new TestableUnsubscribeContext
            {
                Extensions = options.Context
            };

            Assert.That(async() => await terminator.Invoke(context, c => Task.CompletedTask), Throws.InstanceOf <QueueNotFoundException>());

            Assert.AreEqual(0, dispatcher.DispatchedTransportOperations.Count);
            Assert.AreEqual(11, dispatcher.FailedNumberOfTimes);
        }
 /// <summary>
 /// Unsubscribes to receive published messages of the specified type.
 /// </summary>
 /// <param name="eventType">The type of event to unsubscribe to.</param>
 /// <param name="options">Options for the subscribe.</param>
 public virtual Task Unsubscribe(Type eventType, UnsubscribeOptions options)
 {
     unsubscriptions.Enqueue(new Unsubscription(eventType, options));
     return Task.FromResult(0);
 }
 public Task Unsubscribe(Type eventType, UnsubscribeOptions options)
 {
     return(MessageOperations.Unsubscribe(context, eventType, options));
 }
Example #31
0
        /// <summary>
        /// Send email(s) over SendGrid’s v3 Web API
        /// </summary>
        /// <param name="personalizations">The personalizations.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="contents">The contents.</param>
        /// <param name="from">From.</param>
        /// <param name="replyTo">The reply to.</param>
        /// <param name="attachments">The attachments.</param>
        /// <param name="templateId">The template identifier.</param>
        /// <param name="sections">The sections.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="customArgs">The custom arguments.</param>
        /// <param name="sendAt">The send at.</param>
        /// <param name="batchId">The batch identifier.</param>
        /// <param name="unsubscribeOptions">The unsubscribe options.</param>
        /// <param name="ipPoolName">Name of the ip pool.</param>
        /// <param name="mailSettings">The mail settings.</param>
        /// <param name="trackingSettings">The tracking settings.</param>
        /// <param name="cancellationToken">Cancellation token</param>
        /// <returns>
        /// The message id.
        /// </returns>
        /// <exception cref="Exception">Email exceeds the size limit</exception>
        public async Task <string> SendAsync(
            IEnumerable <MailPersonalization> personalizations,
            string subject,
            IEnumerable <MailContent> contents,
            MailAddress from,
            MailAddress replyTo = null,
            IEnumerable <Attachment> attachments = null,
            string templateId = null,
            IEnumerable <KeyValuePair <string, string> > sections = null,
            IEnumerable <KeyValuePair <string, string> > headers  = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            TrackingSettings trackingSettings   = null,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (personalizations != null && personalizations.Any())
            {
                // - The total number of recipients must be less than 1000. This includes all recipients defined within the to, cc, and bcc parameters, across each object that you include in the personalizations array.
                var numberOfRecipients = personalizations.Sum(p => p?.To?.Count(r => r != null) ?? 0);
                numberOfRecipients += personalizations.Sum(p => p?.Cc?.Count(r => r != null) ?? 0);
                numberOfRecipients += personalizations.Sum(p => p?.Bcc?.Count(r => r != null) ?? 0);
                if (numberOfRecipients >= 1000)
                {
                    throw new ArgumentOutOfRangeException("The total number of recipients must be less than 1000");
                }
            }

            var data = new JObject();

            if (from != null)
            {
                data.Add("from", JToken.FromObject(from));
            }
            if (replyTo != null)
            {
                data.Add("reply_to", JToken.FromObject(replyTo));
            }
            if (!string.IsNullOrEmpty(subject))
            {
                data.Add("subject", subject);
            }
            if (contents != null && contents.Any())
            {
                data.Add("content", JToken.FromObject(contents.ToArray()));
            }
            if (attachments != null && attachments.Any())
            {
                data.Add("attachments", JToken.FromObject(attachments.ToArray()));
            }
            if (!string.IsNullOrEmpty(templateId))
            {
                data.Add("template_id", templateId);
            }
            if (categories != null && categories.Any())
            {
                data.Add("categories", JToken.FromObject(categories.ToArray()));
            }
            if (sendAt.HasValue)
            {
                data.Add("send_at", sendAt.Value.ToUnixTime());
            }
            if (!string.IsNullOrEmpty(batchId))
            {
                data.Add("batch_id", batchId);
            }
            if (unsubscribeOptions != null)
            {
                data.Add("asm", JToken.FromObject(unsubscribeOptions));
            }
            if (!string.IsNullOrEmpty(ipPoolName))
            {
                data.Add("ip_pool_name", ipPoolName);
            }
            if (mailSettings != null)
            {
                data.Add("mail_settings", JToken.FromObject(mailSettings));
            }
            if (trackingSettings != null)
            {
                data.Add("tracking_settings", JToken.FromObject(trackingSettings));
            }

            if (personalizations != null && personalizations.Any())
            {
                // It's important to make a copy of the personalizations to ensure we don't modify the original array
                var personalizationsCopy = personalizations.ToArray();
                foreach (var personalization in personalizationsCopy)
                {
                    personalization.To  = EnsureRecipientsNamesAreQuoted(personalization.To);
                    personalization.Cc  = EnsureRecipientsNamesAreQuoted(personalization.Cc);
                    personalization.Bcc = EnsureRecipientsNamesAreQuoted(personalization.Bcc);
                }

                data.Add("personalizations", JToken.FromObject(personalizationsCopy));
            }

            if (sections != null && sections.Any())
            {
                var sctns = new JObject();
                foreach (var section in sections)
                {
                    sctns.Add(section.Key, section.Value);
                }

                data.Add("sections", sctns);
            }

            if (headers != null && headers.Any())
            {
                var hdrs = new JObject();
                foreach (var header in headers)
                {
                    hdrs.Add(header.Key, header.Value);
                }

                data.Add("headers", hdrs);
            }

            if (customArgs != null && customArgs.Any())
            {
                var args = new JObject();
                foreach (var customArg in customArgs)
                {
                    args.Add(customArg.Key, customArg.Value);
                }

                data.Add("custom_args", args);
            }

            // Sendgrid does not allow emails that exceed 30MB
            var contentSize = JsonConvert.SerializeObject(data, Formatting.None).Length;

            if (contentSize > MAX_EMAIL_SIZE)
            {
                throw new Exception("Email exceeds the size limit");
            }

            var response = await _client
                           .PostAsync($"{_endpoint}/send")
                           .WithJsonBody(data)
                           .WithCancellationToken(cancellationToken)
                           .AsResponse()
                           .ConfigureAwait(false);

            var messageId = (string)null;

            if (response.Message.Headers.Contains("X-Message-Id"))
            {
                messageId = response.Message.Headers.GetValues("X-Message-Id").FirstOrDefault();
            }

            return(messageId);
        }
Example #32
0
        /// <summary>
        /// Send email(s) over SendGrid’s v3 Web API.
        /// </summary>
        /// <param name="personalizations">The personalizations.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="contents">The contents.</param>
        /// <param name="from">From.</param>
        /// <param name="replyTo">The reply-to addresses.</param>
        /// <param name="attachments">The attachments.</param>
        /// <param name="templateId">The template identifier.</param>
        /// <param name="headers">The headers.</param>
        /// <param name="categories">The categories.</param>
        /// <param name="customArgs">The custom arguments.</param>
        /// <param name="sendAt">The send at.</param>
        /// <param name="batchId">The batch identifier.</param>
        /// <param name="unsubscribeOptions">The unsubscribe options.</param>
        /// <param name="ipPoolName">Name of the ip pool.</param>
        /// <param name="mailSettings">The mail settings.</param>
        /// <param name="trackingSettings">The tracking settings.</param>
        /// <param name="priority">The priority.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>
        /// The message id.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">Too many recipients.</exception>
        /// <exception cref="Exception">Email exceeds the size limit.</exception>
        public async Task <string> SendAsync(
            IEnumerable <MailPersonalization> personalizations,
            string subject,
            IEnumerable <MailContent> contents,
            MailAddress from,
            IEnumerable <MailAddress> replyTo    = null,
            IEnumerable <Attachment> attachments = null,
            string templateId = null,
            IEnumerable <KeyValuePair <string, string> > headers = null,
            IEnumerable <string> categories = null,
            IEnumerable <KeyValuePair <string, string> > customArgs = null,
            DateTime?sendAt = null,
            string batchId  = null,
            UnsubscribeOptions unsubscribeOptions = null,
            string ipPoolName                   = null,
            MailSettings mailSettings           = null,
            TrackingSettings trackingSettings   = null,
            MailPriority priority               = MailPriority.Normal,
            CancellationToken cancellationToken = default)
        {
            if (_client?.BaseClient?.DefaultRequestHeaders?.Authorization?.Scheme?.Equals("Basic", StringComparison.OrdinalIgnoreCase) ?? false)
            {
                const string errorMessage  = "SendGrid does not support Basic authentication when sending transactional emails.";
                const string diagnosticLog = "This request was not dispatched to SendGrid because the exception returned by their API in this scenario is not clear: 'Permission denied, wrong credentials'.";
                throw new SendGridException(errorMessage, null, diagnosticLog);
            }

            if (personalizations == null || !personalizations.Any())
            {
                throw new ArgumentNullException(nameof(personalizations));
            }

            // This comparer is used to perform case-insensitive comparisons of email addresses
            var emailAddressComparer = new LambdaComparer <MailAddress>((address1, address2) => address1.Email.Equals(address2.Email, StringComparison.OrdinalIgnoreCase));

            // It's important to make a copy of the personalizations to ensure we don't modify the original array
            var personalizationsCopy = personalizations.Where(p => p != null).ToArray();

            foreach (var personalization in personalizationsCopy)
            {
                // Make sure the arrays are not null otherwise Linq's 'Except' method will throw a ArgumentNull exception (See GH-286).
                if (personalization.To == null)
                {
                    personalization.To = Array.Empty <MailAddress>();
                }
                if (personalization.Cc == null)
                {
                    personalization.Cc = Array.Empty <MailAddress>();
                }
                if (personalization.Bcc == null)
                {
                    personalization.Bcc = Array.Empty <MailAddress>();
                }

                // Avoid duplicate addresses. This is important because SendGrid does not throw any
                // exception when a recipient is duplicated (which gives you the impression the email
                // was sent) but it does not actually send the email
                personalization.To = personalization.To
                                     .Distinct(emailAddressComparer)
                                     .ToArray();
                personalization.Cc = personalization.Cc
                                     .Distinct(emailAddressComparer)
                                     .Except(personalization.To, emailAddressComparer)
                                     .ToArray();
                personalization.Bcc = personalization.Bcc
                                      .Distinct(emailAddressComparer)
                                      .Except(personalization.To, emailAddressComparer)
                                      .Except(personalization.Cc, emailAddressComparer)
                                      .ToArray();

                // SendGrid doesn't like empty arrays
                if (!personalization.To.Any())
                {
                    personalization.To = null;
                }
                if (!personalization.Cc.Any())
                {
                    personalization.Cc = null;
                }
                if (!personalization.Bcc.Any())
                {
                    personalization.Bcc = null;
                }

                // Surround recipient names with double-quotes if necessary
                personalization.To  = EnsureRecipientsNamesAreQuoted(personalization.To);
                personalization.Cc  = EnsureRecipientsNamesAreQuoted(personalization.Cc);
                personalization.Bcc = EnsureRecipientsNamesAreQuoted(personalization.Bcc);

                // Indicate if a dynamic template is being used. This is used by MailPersonalizationConverter to generate the appropriate JSON
                personalization.IsUsedWithDynamicTemplate = Template.IsDynamic(templateId);
            }

            // The total number of recipients must be less than 1000. This includes all recipients defined within the to, cc, and bcc parameters, across each object that you include in the personalizations array.
            var numberOfRecipients = personalizationsCopy.Sum(p => p.To?.Count(r => r != null) ?? 0);

            numberOfRecipients += personalizationsCopy.Sum(p => p.Cc?.Count(r => r != null) ?? 0);
            numberOfRecipients += personalizationsCopy.Sum(p => p.Bcc?.Count(r => r != null) ?? 0);
            if (numberOfRecipients >= 1000)
            {
                throw new ArgumentOutOfRangeException(nameof(numberOfRecipients), numberOfRecipients, "The total number of recipients must be less than 1000");
            }

            // Get the priority headers
            if (!_priorityHeaders.TryGetValue(priority, out KeyValuePair <string, string>[] priorityHeaders))
            {
                throw new Exception($"{priority} is an unknown priority");
            }

            // Combine headers with priority headers making sure not to duplicate priority headers
            var combinedHeaders = (headers ?? Array.Empty <KeyValuePair <string, string> >())
                                  .Where(kvp => !priorityHeaders.Any(p => p.Key.Equals(kvp.Key, StringComparison.OrdinalIgnoreCase)))
                                  .Concat(priorityHeaders);

            // Remove duplicates from the list of 'reply-to' addresses
            var cleanReplyTo = replyTo?.Distinct(emailAddressComparer) ?? Enumerable.Empty <MailAddress>();

            // SendGrid allows no more than 1000 'reply-to' addresses
            var numberOfReplyToAddresses = cleanReplyTo.Count();

            if (numberOfReplyToAddresses > 1000)
            {
                throw new ArgumentOutOfRangeException(nameof(numberOfReplyToAddresses), numberOfReplyToAddresses, "The number of distinct reply-to addresses can't exceed 1000");
            }

            // Serialize the mail message
            var data = new StrongGridJsonObject();

            data.AddProperty("from", from);
            data.AddProperty("reply_to_list", cleanReplyTo);
            data.AddProperty("subject", subject);
            data.AddProperty("content", contents);
            data.AddProperty("attachments", attachments);
            data.AddProperty("template_id", templateId);
            data.AddProperty("categories", categories);
            data.AddProperty("send_at", sendAt?.ToUnixTime());
            data.AddProperty("batch_id", batchId);
            data.AddProperty("asm", unsubscribeOptions);
            data.AddProperty("ip_pool_name", ipPoolName);
            data.AddProperty("mail_settings", mailSettings);
            data.AddProperty("tracking_settings", trackingSettings);
            data.AddProperty("personalizations", personalizationsCopy);
            data.AddProperty("headers", ConvertEnumerationToJson(combinedHeaders));
            data.AddProperty("custom_args", ConvertEnumerationToJson(customArgs));

            // SendGrid does not allow emails that exceed 30MB
            var serializedContent = JsonSerializer.Serialize(data, typeof(StrongGridJsonObject), JsonFormatter.SerializationContext);

            if (serializedContent.Length > MAX_EMAIL_SIZE)
            {
                throw new Exception("Email exceeds the size limit");
            }

            // Send the request
            var response = await _client
                           .PostAsync($"{_endpoint}/send")
                           .WithJsonBody(data)
                           .WithCancellationToken(cancellationToken)
                           .AsResponse()
                           .ConfigureAwait(false);

            // Get the messageId from the response
            return(response.Message.Headers.GetValue("X-Message-Id"));
        }
Example #33
0
 public Task Unsubscribe(Type eventType, UnsubscribeOptions options) => Task.CompletedTask;
 /// <summary>
 /// Unsubscribes to receive published messages of the specified type.
 /// </summary>
 /// <param name="eventType">The type of event to unsubscribe to.</param>
 /// <param name="options">Options for the subscribe.</param>
 public virtual Task Unsubscribe(Type eventType, UnsubscribeOptions options, CancellationToken cancellationToken = default)
 {
     unsubscriptions.Enqueue(new Unsubscription(eventType, options));
     return(Task.FromResult(0));
 }
 public Task Unsubscribe(Type eventType, UnsubscribeOptions options)
 {
     throw new NotImplementedException();
 }
 public UnsubscribeResult Unsubscribe(IEnumerable<string> members, UnsubscribeOptions options = UnsubscribeOptions.None)
 {
     return Unsubscribe(members.Cat(), options);
 }
        public UnsubscribeResult Unsubscribe(string members, UnsubscribeOptions options = UnsubscribeOptions.None)
        {
            var result = new UnsubscribeResult();

            if (!String.IsNullOrWhiteSpace(members))
            {
                var req = new RestRequest();
                req.AddParameter("unsubscribees", members);
                req.AddParameter("send_unsub_ack_to_this_batch", options.HasFlag(UnsubscribeOptions.SendAcknowledgement).ToInt());
                req.AddParameter("send_unsub_notifications_to_list_owner", options.HasFlag(UnsubscribeOptions.NotifyOwner).ToInt());

                var resp = this.GetClient().ExecutePostAdminRequest(_removePage, req);
                var doc = GetHtmlDocument(resp.Content);
                
                string xpath = "//h5[contains(translate(text(), 'SU', 'su'), 'successfully unsubscribed')]/following-sibling::ul[1]/li";
                foreach (var node in doc.DocumentNode.SafeSelectNodes(xpath))
                    result.Unsubscribed.Add(node.InnerText.Trim());

                xpath = "//h3[descendant::*[contains(translate(text(), 'CU', 'cu'), 'cannot unsubscribe')]]/following-sibling::ul[1]/li";
                foreach (var node in doc.DocumentNode.SafeSelectNodes(xpath))
                    result.NonMembers.Add(node.InnerText.Trim());

                if (_emailListPopulated)
                    PopulateEmailList();
            }

            return result;
        }