2

I am looking for an advice on how to implement the structure of solution/projects.

Currently, (written in .Net Core 2.0) I have a Web API project which is the main project. Then there is DAL (for accessing the database), BusinessLayerproject and an authentication server project.

The whole stack is to be run in a Linux environment.

I am looking for a way to add mail sending logic to the above solution. There are 2 cases:

  1. (Active) Send notification when a new user is registered or a password reset is triggered (via Web API)
  2. (Passive) Send out monthly statistical data to users / send out recurring notifications (via ???)

Now, if this solution was to be deployed on Windows - I would have created a new WindowsService project to send out passive notifications + added a mail sender service to Web API project. But now that the Linux is used, I am running out of options.

My current planned approach is following:

  1. Inject MailSender service into Web API controller to send out active notifications.
  2. Add a new Console project, to send out recurring notifications (passive ones).
  3. Add a crontab entry in Linux for the above mentioned console program, with a given time interval/delays. It will launch console app and execute mail sending for passive notifications.

Before I dig too deep into this - is there any better solution? Or is my proposed solution any good?

Worth saying, that I am planning to use Razor templating for mails. So whatever the project is going to be used - it needs to support that.

Alex
  • 4,607
  • 9
  • 61
  • 99
  • You said you would have created service on windows - you can do the same on linux. – Evk Nov 29 '17 at 19:28
  • You can create a cronjob that runs a `powershell` script in the background for sending passive emails...the active solutions that you pointed out seems fine to me... – Hackerman Nov 29 '17 at 19:30
  • 2
    I'd actually recommend your crontab job does no more than call an API endpoint exposed by your web application. – Dylan Nicholson Nov 29 '17 at 20:02
  • @DylanNicholson Hm.. Is it then possible to forbid an access to the endpoint by anything, but a localhost? Sounds like a good idea – Alex Nov 29 '17 at 20:14
  • After a further though. This seems to be something that needs to be configured in `Apache`. As far as the `Kestrel` is concerned - he is already listening to `localhost` requests. So it's a proxy's job to filter out requests from the outside to protected API endpoint.. – Alex Nov 29 '17 at 20:22
  • 2
    If it's for an enterprise system you'd probably want to look at some sort of WAF or gateway product that is able to ensure any APIs only intended for internal use are not allowed to be called from external networks. IIS/ASP.NET has the ability to do IP-address based security, I'm not sure whether the built-in ASP.NET core web service (Kestrel?) has such a thing. – Dylan Nicholson Nov 29 '17 at 20:24
  • @DylanNicholson Normally, `Kestrel` is not exposed to the Internet. `Kestrel` is listening on localhost + some port. I think it's proxy's job (`IIS`, `Apache`, `Nginx`) to do the filtering job. This is a totally viable option, though, I will need to do some digging first :) Thank you. – Alex Nov 29 '17 at 20:26
  • I don't see why cron job would call your web api (?) to send email, what's the point? – Evk Nov 29 '17 at 20:40
  • Because the web service has all the configuration information etc. necessary to send emails. If you want to send from a separate tool, it would have to be able to read the config info with the SMTP server details etc. Plus for instance if you move to Azure or AWS they have their own mechanisms for doing "cron"/scheduled jobs, that can only call HTTP(S) endpoints. – Dylan Nicholson Nov 29 '17 at 22:35

1 Answers1

1

Alright, after having a discussion in Comments section I will finalize my thoughts on this matter in this answer. As was suggested by user:

  • Evk:

You said you would have created service on windows - you can do the same on linux.

I am not sure what idea is hidden here, since there is no WindowsService project in .Net Core list or similar type of core project (as of effective date 30.11.2017). So perhaps this suggestion can be clarified more? Therefore, not an option for me right now.

  • Hackerman

You can create a cronjob that runs a powershell script in the background for sending passive emails...the active solutions that you pointed out seems fine to me.

I can agree that PowerShell made a great progress in recent years. There is now a core version of it, supported on Linux as well! The simplified implementation for above suggestion would be to create a library for sending out mails, compile it (as DLL) and then reference the library and underlying methods from within a PS script. A good tutorial for it is here.

> [Reflection.Assembly]::LoadFile("c:\temp\MyMathLib.dll")
> [MyMathLib.Methods]::Sum(10, 2)

> $mathInstance = new-object MyMathLib.Methods
> $mathInstance.Product(10, 2)

I personally don't like the suggestion, as it abstracts the library in a PowerShell, rather than execute methods directly. This solution is harder to debug. Then, for the power shell, you will still need to register a crontab job. Viable option, but not good enough for me.

  • Dylan Nicholson

I'd actually recommend your crontab job does no more than call an API endpoint exposed by your web application.

A simple thought, but with a deep meaning inside it. Now, as Dylan has suggested - we can create a new API endpoint (new Web API controller perhaps) that will hold the data processing, aggregation and mail sending logic! In this case - there is no need for an additional level of abstraction, such as powershell or console app. No need for a separate project.

The only issue with this suggestion - the endpoint should not be accessible by the outer world. Normally (as suggested by .net Core devs), Kestrel will not be exposed to the Internet. Kestrel is listening on localhost for the requests. Contact to the outer world is made through proxy. On Windows, it will most likely be IIS, on Linux - either Apache or Ngix. Therefore, the idea, is that it's proxy's job to do the filtering of the incoming requests.

A good starting point for excluding public endpoint in Apache would be this and this threads.

Lastly, there is an option to go with my original idea. Create a console app, which will serve as a service. But I prefer the above mentioned solution instead.

Alex
  • 4,607
  • 9
  • 61
  • 99