-4

I've developed a C# web app MVC that gets some information from another site (Trello) through API calls, and allows the user to do some actions like printing an .xls file with all card details. Now, I want to implement a functionality that sends every day at a specific time in background a mail to my Gmail account with that Excel as an attachment. I want to implement that functionality in an external project but in the same solution, but I don't know how to do that, I heard about quartz.net but I didn't understand how it works and I don't know if that's the right solution. Can anyone help me and give me some tips?

p.s. I can't host the app

EDIT - New question


When I try to implement my background job with Quartz.Net I got this error that my class SendMailJob doesn't implement an interface member IJob.Execute.

What i have to do?

This is my jobs class:

public class SendMailJob : IJob
{
    public void SendEmail(IJobExecutionContext context)
    {
        MailMessage Msg = new MailMessage();

        Msg.From = new MailAddress("mymail@mail.com", "Me");

        Msg.To.Add(new MailAddress("receivermail@mail.com", "ABC"));

        Msg.Subject = "Inviare Mail con C#";

        Msg.Body = "Mail Sended successfuly";
        Msg.IsBodyHtml = true;

        SmtpClient Smtp = new SmtpClient("smtp.live.com", 25);

        Smtp.DeliveryMethod = SmtpDeliveryMethod.Network;

        Smtp.UseDefaultCredentials = false;
        NetworkCredential Credential = new
        NetworkCredential("mymail@mail.com", "password");
        Smtp.Credentials = Credential;

        Smtp.EnableSsl = true;

        Smtp.Send(Msg);
    }
}
Lutti Coelho
  • 2,134
  • 15
  • 31
Limi Derjaj
  • 45
  • 1
  • 10
  • 3
    I think something like this would be handled well by a windows service: https://learn.microsoft.com/en-us/dotnet/framework/windows-services/walkthrough-creating-a-windows-service-application-in-the-component-designer – Brandon Miller Dec 16 '19 at 13:58
  • 1
    If you want to run a service in a separate thread on the same application, then Hangfire would also be the right choice! – codeninja.sj Dec 16 '19 at 14:01
  • 4
    @codeninja.sj You mean [Hangfire](https://www.hangfire.io/). But it would be better off hosted in a Windows service or similar, not in a web application. – mason Dec 16 '19 at 14:02
  • If you've already written the code to do what you want, then put it into a console app, make sure it still works as expect on that platform and then run it as a scheduled task. Web applications are not right for this type of requirement. They're only really made to respond to requests. Look at either a scheduled task or a windows service. – Reinstate Monica Cellio Dec 16 '19 at 14:09
  • What do you mean with "I can't host the app". Do you want it to be a background job on your webapp or to use windows service in a local machine? – Lutti Coelho Dec 16 '19 at 14:13
  • i didn't write the code that i want to do because i've never worked with emails in my programming experience, I'm also looking for help on how to send a simple email because I don't know how to do it. – Limi Derjaj Dec 16 '19 at 14:39
  • @LimiDerjaj. To send e-mail with C# take a look at: https://stackoverflow.com/questions/18326738/how-to-send-email-in-asp-net-c-sharp and sendgrid.com – Lutti Coelho Dec 16 '19 at 15:06
  • @LimiDerjaj Sending an email is about 5 lines of code. It's simple. The important part is figuring out *where* the logic should live. – mason Dec 16 '19 at 15:24
  • i wanted to figure this funtionality in an external project in the same solution, what do you think? it id possible? – Limi Derjaj Dec 16 '19 at 16:13
  • @mason where i can find this 5 lines of code to send the email? i got a lot of answers here and they're all different.. – Limi Derjaj Dec 17 '19 at 08:43
  • They're all different because they're showing you different ways of doing it. I'm not just going to give you 5 lines of code to send an email - you can find that in plenty of places on the Internet. You could start with looking at Microsoft's documentation for the SmtpClient class. – mason Dec 17 '19 at 13:18
  • [Please don't edit new questions into old ones](https://meta.stackexchange.com/q/39223/248627). If you have a new question, post it as a new question. – ChrisGPT was on strike Dec 18 '19 at 16:35

3 Answers3

1

You can create a windows service or create a console application and schedule it in windows scheduler.I have implemented the Send-mail service using Windows services.

Mr_rk
  • 19
  • 4
  • i've nevere used them, i don't have a lot of experience on programming, there are some tutorials or documents that can help me with this? – Limi Derjaj Dec 16 '19 at 14:26
  • For creating windows service you can check this article https://www.c-sharpcorner.com/UploadFile/8a67c0/create-and-install-windows-service-step-by-step-in-C-Sharp/ .You can Insert the data you want to mail in database tables and then create windows service looping through the data you want to send . – Mr_rk Dec 16 '19 at 14:32
1

If you really want to it as background job on a Asp.Net WebApp you should look into:


Quartz.Net

Create a job to send e-mail

public class SendMailJob : IJob
{
    public void Execute(IJobExecutionContext context)
    {
        ...Do your stuff;
    }
}

Then configure your job to execute daily

// define the job and tie it to our SendMailJob class
IJobDetail job = JobBuilder.Create<SendMailJob>()
    .WithIdentity("job1", "group1")
    .Build();

// Trigger the job to run now, and then repeat every 24 hours
ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("trigger1", "group1")
    .StartNow()
    .WithSimpleSchedule(x => x
        .WithIntervalInHours(24)
        .RepeatForever())
    .Build();

HangFire

RecurringJob.AddOrUpdate(
    () => YourSendMailMethod("email@email.com"),
    Cron.Daily);

IHostedService

public class SendMailHostedService : IHostedService, IDisposable
{
    private readonly ILogger<SendMailHostedService> _logger;
    private Timer _timer;

    public SendMailHostedService(ILogger<SendMailHostedService> logger)
    {
        _logger = logger;
    }

    public Task StartAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Hosted Service running.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero, 
            TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        //...Your stuff here

        _logger.LogInformation(
            "Timed Hosted Service is working. Count: {Count}", executionCount);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

In your startup.cs class. add this at configure method.

services.AddHostedService<SendMailHostedService>();

If do not need to host it as a backgroud job on your WebApp, then you can create a Windows Service that runs every day on the time you need.

See this question: Windows service scheduling to run daily once a day at 6:00 AM


To send E-mails with C# you can take a look a SmptClient class https://learn.microsoft.com/en-us/dotnet/api/system.net.mail.smtpclient.send?view=netframework-4.8

Or use a service, like SendGrid, that can do it for you.

EDIT:


About your second question:

When you implements an interface your class should have all methods defined on that interface.

This methods needs to be public, return the same type, has the same name and receive the same parameters that was declared on the interface you implement.

In your specific case, you just miss the method name. Just change it do Execute like below.

EDIT: As you are using Quartz.net 3, the IJbo interface returns a Task and not void. So I changed the class SendMailJob to return a task of your existing method.

public class SendMailJob : IJob
{
    public Task Execute(IJobExecutionContext context)
    {
        return Task.Factory.StartNew(() => SendEmail());
    }

    public void SendMail()
    {
        MailMessage Msg = new MailMessage();

        Msg.From = new MailAddress("mymail@mail.com", "Me");

        Msg.To.Add(new MailAddress("receivermail@mail.com", "ABC"));

        Msg.Subject = "Inviare Mail con C#";

        Msg.Body = "Mail Sended successfuly";
        Msg.IsBodyHtml = true;

        SmtpClient Smtp = new SmtpClient("smtp.live.com", 25);

        Smtp.DeliveryMethod = SmtpDeliveryMethod.Network;

        Smtp.UseDefaultCredentials = false;
        NetworkCredential Credential = new
        NetworkCredential("mymail@mail.com", "password");
        Smtp.Credentials = Credential;

        Smtp.EnableSsl = true;

        Smtp.Send(Msg);
    }
}
Lutti Coelho
  • 2,134
  • 15
  • 31
  • hi i wrote the code to send the email and it works (i've tried to send the email when i click a button in the index view, just for try if the code, and it was correct) now i wanted to do it as a daily background job with Quartz.net like you reccomended me. I've created a new class SendEmailJob : IJob but it tells me that it doesn't implement an interface member IJob.Execute, what i have to do? – Limi Derjaj Dec 18 '19 at 09:06
  • I do not reccomended Quartz. I just give you options. Quartz.net is one of this options. – Lutti Coelho Dec 18 '19 at 09:12
  • @Limi Please update your question with the code of your SendEmailJob class – Lutti Coelho Dec 18 '19 at 09:13
  • i've updated my question, the problem is here: public class SendMailJob : IJob (i don't know why the first part of the code is not shown as a code) – Limi Derjaj Dec 18 '19 at 09:20
  • Please. Please. Please. Please. Please. Please. Please. Do not change all context of your question after you got answers. It will be really hard for others users understand the problem and the solution. Remember that StackOverflow only is a good site today because it is very organized. Let's keep it organized. I edited your question for you, but it will only appear for you after moderator's review. – Lutti Coelho Dec 18 '19 at 10:15
  • For now. Just change the name of the SendEmail method to Execute and then study about how interfaces works. – Lutti Coelho Dec 18 '19 at 10:17
  • I edited my answer with some information about interfaces and how to fix your code. Happy I could help. – Lutti Coelho Dec 18 '19 at 10:23
  • To configure my job to execute daily i just need the two paragraphs that you answered to me (Create a job, and configure it to execute daily) ? I'm searching for a tutorial on how to use quartz properly because i didn't understand how it works... and in the : IJob it still give me an error: Cannot implement the IJob.Execute because it doesn't have the matching return type of 'Task – Limi Derjaj Dec 18 '19 at 10:49
  • @Limi. You start the question asking how to do a background job in asp.net. Now we are talking about specifics of Quartz.Net. Please could you create a new question about this new doubts? – Lutti Coelho Dec 18 '19 at 10:56
  • i can't create the question, i have to wait 2 days haha i'm sorry for the mistakes i made, i thought that my question was inherent with quartz.net specific because it is the solution for my question – Limi Derjaj Dec 18 '19 at 11:09
  • Try this: public async Task Execute(IJobExecutionContext context) – Lutti Coelho Dec 18 '19 at 11:40
  • it need the await? or i don't need to write it? – Limi Derjaj Dec 18 '19 at 11:42
  • Try remove the async from method. It will not ask for the await. I forgot your method is not async. – Lutti Coelho Dec 18 '19 at 11:44
  • it tells me not all code paths return a value, maybe i have to put the part of code to configure my job to execute daily? – Limi Derjaj Dec 18 '19 at 13:03
  • @LimiDerjaj I realize that you are using Quartz.net 3. That has some little chages from my previous example. So I update it with tha changes needed. – Lutti Coelho Dec 19 '19 at 13:04
  • @LimiDerjaj did it help you? Could you implement your solution? – Lutti Coelho Dec 22 '19 at 20:26
  • 1
    hi, i have just tried it and it works, thank you very much – Limi Derjaj Dec 23 '19 at 08:00
  • 1
    Good. As it helped you can you mark it as correct, or upvote? It will help other users with the same problem on the future too. – Lutti Coelho Dec 23 '19 at 12:34
  • 1
    where can i mark it as corrected? – Limi Derjaj Dec 24 '19 at 11:45
  • 1
    On the left side of the answer. Bellow the down vote button. It look like a V – Lutti Coelho Dec 24 '19 at 13:14
0

Use a library like Hangfire which lets you schedule background jobs and backs them with persistent storage.

You can then easily schedule a recurring job like:

RecurringJob.AddOrUpdate(
    () => SendEmail("user@domain"),
    Cron.Daily);

https://docs.hangfire.io/en/latest/tutorials/index.html - the first tutorial is about sending email

Owen Pauling
  • 11,349
  • 20
  • 53
  • 64