Email Blaster: My additions

Wed Apr 26, 2023 | 587 Words

What is Email Blaster?

Email Blaster is a project I wrote as part of the “The Complete .NET Coding Bootcamp Course” from Coder Foundry. In this blog post I’ll talk about the tweaks I added to the webapp. The project is written in C# using .NET MVC, PostgreSQL, Microsoft Identity, Entity Framework Core, Mailkit, and MimeKit.

Here is the finished project, please check out the demo!: https://emailblaster.up.railway.app/


Now let me briefly talk about the tweaks I made to the project:

1. Filter by State

View of the contacts page.

As you can see in this picture there is a search, filter by contact’s category, and filter by state. I added the filter by state functionality. Since a Contact’s States are in an enum list I created a variable “stateResult” using:

var contact = from s in _context.Contacts select s;
var stateResult = from States s in Enum.GetValues(typeof(States)) select new { Id = s.ToString(), Name = s.ToString() };
ViewData["States"] = new SelectList(stateResult, "Id", "Name",  state);

to put those fields into the view and then as I’d already written out the if else statement for filtering by category I added an else if for filtering by state:

if (appUser != null)
            {
                if (catId == 0 && state == null || state == "All Contacts")
                {
                    contacts = appUser.Contacts.OrderBy(c => c.FullName).ToList();
                }
                
                else if (catId != 0)
                {
                    contacts = appUser.Categories.FirstOrDefault(c => c.Id == catId)!
                        .Contacts
                        .OrderBy(c => c.FirstName)
                        .ThenBy(c => c.LastName)
                        .ToList();
                }
                //Add in the state filter.
                else if (state != null)
                {
                    contacts = contact.Where(c => c.State == (States)Enum.Parse(typeof(States), state))
                        .OrderBy(c => c.FirstName)
                        .ThenBy(c => c.LastName)
                        .ToList();

                }
            }

This allows for filtering the contacts before returning them to the view so users can filter by a contacts’ state.

2. Demo User

I got advice to use a helper function we made in the course to register a demo account on program initialize then have a button to automatically log a user into that specific account. By having this in the helper function all I had to do to have it run at startup was go back to the Program.cs and write await DataHelper.SeedAdminAsync(scope.ServiceProvider); as we’d already used var scope = app.Services.CreateScope(); to run another DataHelper function.

Now all SeedAdminAsync does is hit up the UserManager and IConfiguration using .GetRequiredService then makes sure the email I’m setting the account to isn’t already registered with if (await userManager.FindByEmailAsync("email") == null) then it creates a new AppUser “demoUser” (extended from IdentityUser) with all the fields set to something and EmailConfirmed set to true. It also sets the password from an environment variable so that’s hidden using await userManager.CreateAsync(demoUser, config.GetSection("demoPassword)["Password] ?? Environment.GetEnvironmentVariable("demoPassword"));

After this is set up creating the button to log into the app on the log in page was relatively easy, as I had scaffolded the Microsoft Identity pages out previously in this course all I had to do was go to the log in page and add

<h2>Use demo account:</h2>
            <form id="account" method="post" class="mb-5">               
                <button id="login-submit" type="submit" class="btn btn-lg btn-primary" value="demoLogin" name="demoLogin" onclick="this.form.submit()">DEMO APPLICATION</button>
            </form>

on the cshtml and

var pass = _configuration.GetRequiredSection("demoPassword")["Password"] ?? Environment.GetEnvironmentVariable("demoPassword");
            var demo = await _signInManager.PasswordSignInAsync("email", pass, false, lockoutOnFailure: false);
            if (demo.Succeeded && !string.IsNullOrEmpty(demoLogin))
            {
                _logger.LogInformation("User is logged in");
                return LocalRedirect(returnUrl);
            }

on the code behind. So that is how I added the demo user account.


This is the first project I’ve fully completed for this course and cannot wait to build more projects soon, hopefully with more blog posts talking about how I extended those projects as well. Please do heck out the live project. 🙂