My BCC recipients are not receiving emails - c#

This is my method for building the e-mail object and sending it:
public async Task SendEmail(List<ApplicationUser> bccUsers, string subject, string contentText, string contentHtml)
{
if (bccUsers.Count > 0)
{
var client = new SendGridClient("MyClientKey");
var from = new EmailAddress("noreply#domain", "MyProjectName");
var to = new EmailAddress("noreply#domain", "MyProjectName");
var msg = MailHelper.CreateSingleEmail(from, to, subject, contentText, contentHtml);
foreach (ApplicationUser user in bccUsers)
{
msg.AddBcc(user.Email, $"{user.FirstName} {user.LastName}");
}
await client.SendEmailAsync(msg);
}
}
I have confirmed that all the e-mail addresses are receiving other e-mails.
When inspecting the msg-object, all the BCC recipients are there:
What am I doing wrong?
Update
I don't know if this is relevant info, but all the three e-mail addresses are being forwarded to my gmail-address. I am only checking emails there.
One of those addresses is in use, and I am receiving emails to it regularly.
The other two addresses I have just created for testing purposes. They do not have mailboxes of their own at the hosting company, only forwarding to my gmail address.

Related

How do I call a method to automatically send an email in the controller?

I need to be able to send automatic emails to any users who have registered new accounts, changed passwords, and/or created new orders.
I've been given the SendEmail file, which belongs in the "Utilities" folder in my solution.
using System;
using System.Net.Mail;
using System.Net;
namespace SendEmail
{
public static class EmailMessaging
{
public static void SendEmail(String toEmailAddress, String emailSubject, String emailBody)
{
//Create a variable for YOUR TEAM'S Email address
//This is the address that will be SENDING the emails (the FROM address)
String strFromEmailAddress = "email#gmail.com";
//This is the password for YOUR TEAM'S "fake" Gmail account
String strPassword = "Password";
//This is the name of the business from which you are sending
//TODO: Change this to the name of the company you are creating the website for
String strCompanyName = "Team Final Project";
//Create an email client to send the emails
//port 587 is required to work, do not change it
var client = new SmtpClient("smtp.gmail.com", 587)
{
UseDefaultCredentials = false,
//This is the SENDING email address and password
//This will be your team's email address and password
Credentials = new NetworkCredential(strFromEmailAddress, strPassword),
EnableSsl = true
};
//Add anything that you need to the body of the message
//emailBody is passed into the method as a parameter
// /n is a new line – this will add some white space after the main body of the message
//TODO: Change or remove the disclaimer below
String finalMessage = emailBody + "\n\n Thank you, come back again soon!";
//Create an email address object for the sender address
MailAddress senderEmail = new MailAddress(strFromEmailAddress, strCompanyName);
//Create a new mail message
MailMessage mm = new MailMessage();
//Set the subject line of the message (including your team number)
mm.Subject = "Team ## - " + "Thank you!";
//Set the sender address
mm.Sender = senderEmail;
//Set the from address
mm.From = senderEmail;
//Add the recipient (passed in as a parameter) to the list of people receiving the email
mm.To.Add(new MailAddress(toEmailAddress));
//Add the message (passed)
mm.Body = finalMessage;
//send the message!
client.Send(mm);
}
}
}
My problem is that neither I nor my team members know how to implement call this from the controller in a way that will be sent automatically and with the user's email and name. We imagine they will be in the Account and Orders controllers. The accounts controller has the register and change password methods, which work, and the orders controller has the complete order method.
Also, we are not using a confirmation view, it has to be an automatic email.
We need some direction in figuring out where exactly we need to call the method from and how.
The most helpful thing I've found on the internet today is this block of code for a test message that is not intended to be sending automatic emails.
public static void CreateTestMessage(string server)
{
MailAddress from = new MailAddress("sender#gmail.com", "Team Project");
MailAddress to = new MailAddress("reciever#gmail.com", "Customer");
MailMessage message = new MailMessage(from, to);
message.Subject = "Password Changed";
message.Body = #"This is a confirmation email that your password has been changed.";
SmtpClient client = new SmtpClient(server);
client.Credentials = CredentialCache.DefaultNetworkCredentials;
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in CreateBccTestMessage(): {0}",
ex.ToString());
}
}
Everything is being coded on MS VS
First create a service for EmailService and put SendEmailAsync Method in it
and call this method on your Controller.
In Method body:
1-Create your message:
var mm = new MailMessage()
2-Then you should build your smtp:
using var smtpClient = new SmtpClient();
3-Then connect it to your server
await smtpClient.ConnectAsync(
"your host",
"port",
SecureSocketOptions.SslOnConnect);
4-Now send your Email:
await smtpClient.SendAsync(mm);
5-Make sure that disconnect from your client:
await smtpClient.DisconnectAsync(true);
Note: It may give you an Exception while Connecting or Sending your Email so don't forget try catch block.
6-For Automation you can use a EmailAccount Table with relation with your Customer Table and keep your message data in it.
for ex: body ,subject..... .
In your Contorller you have your Customer So you can get his EmailAccount from DataBase and pass EmailAccount Entity to SendEmailAsync Method.
instead of creating message in body, get it from EmailAccount Entity and then countinue the Steps.
7-Enjoy it :)

EWS forward email as attachment - Cannot open in other email clients

In my program, I am reading an Exchange mailbox using EWS .NET API and forwarding the emails as attachment to an external email address. Code that I have used is below
private void ForwardMessage(ExchangeService exchangeService, EmailMessage item)
{
ResponseMessage responseMessage = item.CreateForward();
item.Load(new PropertySet(BasePropertySet.FirstClassProperties, new
PropertySet(){ItemSchema.MimeContent,
ItemSchema.Subject}));
var mail = new EmailMessage(exchangeService);
var attachment = mail.Attachments.AddFileAttachment(String.Format("
{0}.eml", item.Subject),
item.MimeContent.Content);
String forwardEmailAddresses =
MailProcessorSettings.Default.ForwardEmailAddress;
char[] delimiters = { ',', ';' };
foreach (var emailAddress in forwardEmailAddresses.Split(delimiters,
StringSplitOptions.RemoveEmptyEntries))
{
mail.ToRecipients.Add(emailAddress);
}
mail.Subject = item.Subject;
mail.Send();
}
I am able to open the email forwarded as attachment in Outlook. However, if I send it to Gmail or to other users using different email clients it shows up as a blank attachment.
How do I ensure that the email forwarded as an attachment preserves the original content?
Adding a line indicating the content type of the message seems to fix this issue. Either of the following settings seems to work. After adding the ContentType, I was able to download the attachment from Gmail although I had to use the Outlook Client to open it.
attachment.ContentType = "multipart/alternative"
OR
attachment.ContentType = "message/rfc822"

SendGrid "To" List email ids visible to everyone in the list

I am using SendGrid to send emails to a list of users through a console application in asp.net. I am sending a list of user's email addresses in the AddTo section while sending an email. The code looks like this:
SendGridMessage message = new SendGridMessage();
message.AddTo(new List<string>() { "user1#abc.com", "user2#xyz.com", "user3#abc.com", "user4#xyz.com" });
The email is sent as expected, but in the "To" section of the email, I am able to see all the email ids of users to whom this email was sent(image attached below). I want the email ids to be hidden so that no one misuses the other email ids in the list. Is there anyway I can accomplish this using SendGrid?
Use .AddBcc() instead of .AddTo(). BUT if you do this then you'll have to set the To address to something like "no-reply#example.com" which isn't ideal and might increase the chances of the message ending up in the SPAM or Junk folders of your users.
SO instead, write a for loop to send the email per user.
var emailAddresses = new List<string>() { "user1#abc.com", "user2#xyz.com", "user3#abc.com", "user4#xyz.com" };
for (var emailAddress in emailAddresses)
{
var email = new SendGridMessage();
email.AddTo(emailAddress);
// set other values such as the email contact
// send/deliver email
}
Is the content of the email message the same for everyone? I would assume each person would have different "monthly usage" amounts and if so the for loop would be better...
To send to multiple recipients in SendGrid without them seeing each other, you want to use the X-SMTPAPI header, as opposed to the native SMTP To header.
var header = new Header();
var recipients = new List<String> {"a#example.com", "b#exampe.com", "c#example.com"};
header.SetTo(recipients);
var subs = new List<String> {"A","B","C"};
header.AddSubstitution("%name%", subs);
var mail = new MailMessage
{
From = new MailAddress("please-reply#example.com"),
Subject = "Welcome",
Body = "Hi there %name%"
};
// add the custom header that we built above
mail.Headers.Add("X-SMTPAPI", header.JsonString());
The SMTPAPI header will be parsed by SendGrid, and each recipient will get sent a distinct single-To message.
You need to use personalization for that, there are 2 options:
var message = new SendGridMessage();
message.Personalizations = new List<Personalization>();
foreach(var email in emails)
{
var personalization = new Personalization();
personalization.AddTo(new Email(email));
}
Or:
var message = new SendGridMessage();
foreach(var email in emails)
message.AddTo(email, emails.IndexOf(email));
Alternatively you can also use MailHelper with the showAllRecipients flag:
MailHelper.CreateSingleEmailToMultipleRecipients()

Doubts on sending more than one email asynchronously in MVC3

In my application I have a functionality to save and publish articles. So when I click on "Save and Publish" button three things happened:
Published articles get saved in database.
A Notification email goes to a group of users that a new articles is available.
After sending emails page get redirect to "Article Listing" page without showing any success or failure message for an email.
Now Number of users who will receive emails can vary say for e.g 10, 30 50 and so on. I want to send notification emails asynchronously so that page won't get block until all the mails doesn't go to their receptionists.
Given below is a piece of code from "PublishArticle" action method
foreach (string to in emailIds)
{
ArticleNotificationDelegate proc = Email.Send;
IAsyncResult asyncResult = proc.BeginInvoke(subject, body, to, from, cc, null, null, null);
}
Below I have defined a delegate to invoke Send method
private delegate bool ArticleNotificationDelegate (string subject, string body, string to, string from, string cc, string bcc = null);
and this is the code to send an email:
public static bool Send(string subject, string body, string to, string from, string cc, string bcc = null)
{
bool response;
MailMessage mail = new MailMessage();
MailAddress fromAddress = new MailAddress(from);
mail.To.Add(to);
if (!string.IsNullOrWhiteSpace(cc))
{
mail.CC.Add(cc);
}
if (!string.IsNullOrWhiteSpace(bcc))
{
mail.Bcc.Add(bcc);
}
mail.From = fromAddress;
mail.Subject = subject;
mail.Body = body;
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;
SmtpClient client = new SmtpClient();
try
{
client.Send(mail);
response = true;
}
catch (Exception)
{
response = false;
}
finally
{
client.Dispose();
mail.Dispose();
}
return response;
}
Although this code is working fine but still I want to know that whether my this approach is fine and will not cause any problem in future.
If there is a better approach to accomplish my objective then please suggest me.
Note: As I am using .net framework 4.0 so cannot use the new features of Asyn and await available in 4.5.
Also I had used method client.SendAsync by simply replacing the client.Send and rest of my code in above Send method was same. After this change NO mails were being send and also it did not throw any exception. So I did not go with this change.
I want to send notification emails asynchronously so that page won't get block until all the mails doesn't go to their receptionists.
That's a very dangerous approach, because ASP.NET will feel free to tear down your app domain if there are no active requests. ASP.NET doesn't know that you've queued work to its thread pool (via BeginInvoke). I recommend that you use a solution like HangFire to reliably send email.

C# - Sending Email - STOREDRV.Submission.Exception:OutboundSpamException

I am writing a small utility to help process some MySQL tasks every night and have it email my personal email if it fails (this is a personal project, so no company smtp server or anything, emails going through public outlook accounts).
I tested about 5 times and each send was successful, but now any attempts to send email I get this exception:
Error sending test email: Transaction failed. The server response was: 5.2.0 STOREDRV.Submission.Exception:OutboundSpamException; Failed to process message due to a permanent exception with message WASCL UserAction verdict is not None. Actual verdict is Suspend, ShowTierUpgrade. OutboundSpamException: WASCL UserAction verdict is not None. Actual verdict is Suspend, ShowTierUpgrade.[Hostname=BY2PR0101MB1461.prod.exchangelabs.com]
A bit of an oops on my part - didn't think Outlook would consider it as spam on the 6th try - is there anything I can do in Outlook to correct this?
I am using a service account I created in outlook to send these emails to my personal inbox.
The actual code in question:
class JobMailer
{
private string email_to;
private string email_from;
private string password;
private string email_smtp;
private bool use_ssl;
private int port;
public void Send(string subject, string body)
{
MailMessage mail = new MailMessage(email_from, email_to);
using (SmtpClient client = new SmtpClient
{
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
EnableSsl = use_ssl,
Host = email_smtp,
Timeout = 100000,
Port = port,
Credentials = new NetworkCredential(email_from, password)
})
{
mail.Subject = subject;
mail.Body = body;
client.Send(mail);
}
}
public JobMailer(string emailTo, string smtp, string emailFrom, string pw, int p, bool ssl)
{
email_to = emailTo;
email_from = emailFrom;
password = pw;
email_smtp = smtp;
port = p;
use_ssl = ssl;
}
}
I resolved this by verifying the account I was trying to use. Each time you encounter this error an email is sent to the account with instructions on what you need to do to resolve the error. Typically you will need to verify against a phone number.
Got this error trying to send lots of emails to myself at Outlook.com, using SMTP.
To fix it I simply added a 5 second delay between the sends, for example:
foreach(var mail in mailToSend)
{
await smtpClient.SendMailAsync(mail);
Console.WriteLine("Sent email: " + mail);
await Task.Delay(5000);
}
If you aren't doing this just as a test, then you can contact the Outlook.com team and ask them to whitelist your IP (make sure you have SPF, rDNS, etc. setup first).

Categories