Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send email background service with Hangfire #13

Closed
tiagosarri opened this issue Nov 10, 2020 · 3 comments
Closed

Send email background service with Hangfire #13

tiagosarri opened this issue Nov 10, 2020 · 3 comments
Labels

Comments

@tiagosarri
Copy link

I'm trying to send emails using Hangfire and Postal, but I'm having problems with the HTTPContext. If I execute the shooting through a controller the sending is done without problems, now if I execute a job via Hangfire an expection is generated.

Code startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddHangfire(configuration => configuration
        .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
        .UseSimpleAssemblyNameTypeSerializer()
        .UseRecommendedSerializerSettings()
        .UseSqlServerStorage(Configuration.GetConnectionString("default"), new SqlServerStorageOptions
        {
            CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
            SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
            QueuePollInterval = TimeSpan.Zero,
            UseRecommendedIsolationLevel = true,
            UsePageLocksOnDequeue = true,
            DisableGlobalLocks = true
        }));

    services.Configure<EmailSenderOptions>(Configuration.GetSection("EmailSender"));
    services.AddPostal();
    services.AddTransient<IEmailSenderEnhance, EmailSender>();
    services.AddHttpContextAccessor();
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    var options = new DashboardOptions
    {
        Authorization = new[] { new HangFireAuthorizationFilter() }
    };

    app.UseHangfireDashboard("/hangfire", options);
    app.UseHangfireServer();

    RecurringJob.AddOrUpdate<NotificationServices>("SendNotify-", m => m.Notify(1), Cron.Daily);
}

Code NotificationServices.cs

public class NotificationServices
{
    private readonly IEmailSenderEnhance _emailSender;
    private readonly Config _appConfig;
    private readonly IHttpContextAccessor _httpContextAccessor;

    public NotificationServices(IEmailSenderEnhance emailSender, IOptions<Config> optionsAccessor, IHttpContextAccessor httpContextAccessor)
    {
        _emailSender = emailSender;
        if (optionsAccessor == null) throw new ArgumentNullException(nameof(optionsAccessor));
        _appConfig = optionsAccessor.Value;
        _httpContextAccessor = httpContextAccessor;
    }


    public void Notify(int messageId)
    {
        var listOSs = Task.Run(async () => await this.SendEmail(messageId));
    }

    public async Task SendEmail(int orderID)
    {
        var orderRy = new OrderRepository();
        var order = orderRy.Get_By_ID(orderID);

        try
        {
            var requestPath = new Postal.RequestPath
            {
                PathBase = _httpContextAccessor.HttpContext.Request.PathBase.ToString(),
                Host = _httpContextAccessor.HttpContext.Request.Host.ToString(),
                IsHttps = _httpContextAccessor.HttpContext.Request.IsHttps,
                Scheme = _httpContextAccessor.HttpContext.Request.Scheme,
                Method = _httpContextAccessor.HttpContext.Request.Method
            };

            var emailData = new Postal.Email("SendTest")
            {
                RequestPath = requestPath,
            };

            var emailsCopy = $"{order.Salesman.Email},{order.Salesman2.Email},";

            emailData.ViewData["to"] = emailsCopy;
            emailData.ViewData["Order"] = order;

            await _emailSender.SendEmailAsync(emailData);
        }
        catch (Exception ex)
        {
            
        }
    }
}

The error is in HttpContext: _httpContextAccessor.HttpContext.Request.PathBase.ToString()
Object reference not set to an instance of an object

Is it possible to send e-mails via background with Postal?

@hermanho
Copy link
Owner

There is no HttpContext can be retrieved in background since it is not a http request when Hangfire execute the job. That's why we need the Postal.RequestPath class to create the DefaultHttpContext object in Postal library.

@johanjvr
Copy link

johanjvr commented Nov 28, 2020

@tiagosarri Best way around this is to create the email using Postal and then to serialise it so that hangfire can de-serialise it. Using the smtp client you can then construct a MailMessage which will then allow you to send emails via HangFire.

@DaleCam
Copy link

DaleCam commented Jul 25, 2022

@tiagosarri alternatively simply get what you need out of the httpcontext and pass it as a parameter to the method that creates your email, and use the param instead of the context inside your email. ie:

BackgroundJob.Enqueue(() => SendWelcomeEmail(context.whatever).

public Task SendWelcomeEmail(string username){...send the email in here...}

@github-actions github-actions bot locked and limited conversation to collaborators Nov 12, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

4 participants