Unable to send E-mail with Attachment - c#

My issue is this that I am trying to make use of email sending task at my website for the admin individual.
When he selects the email ids from the available data, adds an attachment and sends the email, it was never received by user. However, if he is using simple mailing ie. without any attachment, user receives it.
Can you help please ?
My coding is given below :-
public partial class SahibAdmin_emailNewsletter : System.Web.UI.Page
{
// ...
private void SendNewsletter(string emailId)
{
System.Web.Mail.MailMessage message = new System.Web.Mail.MailMessage();
message.To = emailId;
message.From = "info#sahibimports.com";
message.Subject = "Please See: Newsletter from Sahib imports";
message.BodyFormat = System.Web.Mail.MailFormat.Text;
message.Body = txtBody.Text.ToString();
if (msgUpload.HasFile)
{
//string strFileName = msgUpload.FileName;
//msgUpload.PostedFile.SaveAs(Server.MapPath(strFileName));
//System.Web.Mail.MailAttachment attach =
// new System.Web.Mail.MailAttachment(Server.MapPath(strFileName));
//message.Attachments.Add(attach);
message.Attachments.Add(new Attachment(
FileUpload.PostedFile.InputStream, FileUpload.FileName));
}
System.Web.Mail.SmtpMail.Send(message);
Response.Flush();
}

According to http://msdn.microsoft.com/en-us/library/6sdktyws.aspx your Attachment constructor is trying to set the ContentType with the second parameter but you're passing in a filename, are you sure that is correct?
You should probably change that part to something like:
ContentType contentType = // create suitable type here based on your file format
Attachment attachment = new Attachment(
FileUpload.PostedFile.InputStream,
contentType
);
attachment.ContentDisposition.FileName = FileUpload.FileName;
message.Attachments.Add(attachment);

You are trying to use System.Net.Mail.Attachment with System.Web.Mail.MailMessage.
These API`s are incompatible with each other. System.Web.Mail.MailMessage only supports System.Web.Mail.MailAttachment, not System.Net.Mail.Attachment.

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 :)

Sendgrid C# bulk email X-SMTPAPI header not working

I am trying to send email with SendGrid to multiple recipients in an ASP.Net C# web application
According to the SendGrid documentation I need to add X-SMTPAPI header to my message in JSON formatted string. I do so, for first check I just added a hand-typed string before building my json email list progamatically here is my code:
string header = "{\"to\": [\"emailaddress2\",\"emailaddress3\"], \"sub\": { \"%name%\": [\"Ben\",\"Joe\"]},\"filters\": { \"footer\": { \"settings\": { \"enable\": 1,\"text/plain\": \"Thank you for your business\"}}}}";
string header2 = Regex.Replace(header, "(.{72})", "$1" + Environment.NewLine);
var myMessage3 = new SendGridMessage();
myMessage3.From = new MailAddress("emailaddress1", "FromName");
myMessage3.Headers.Add("X-SMTPAPI", header2);
myMessage3.AddTo("emailaddress4");
myMessage3.Subject = "Test subject";
myMessage3.Html = "Test message";
myMessage3.EnableClickTracking(true);
// Create credentials, specifying your user name and password.
var credentials = new NetworkCredential(ConfigurationManager.AppSettings["xxxxx"], ConfigurationManager.AppSettings["xxxxx"]);
// Create an Web transport for sending email.
var transportWeb = new Web(credentials);
// Send the email, which returns an awaitable task.
transportWeb.DeliverAsync(myMessage3);
But it just seems to ignore my header, and sends the email to the one email "emailaddress4" used in "addto".
According the documentation if the header JSON is parsed wrongly, then SendGrid sends an email about the error to the email address set in "FROM" field, but I get no email about any error.
Anyone got any idea?
For me using the latest 9.x c# library the only way I could solve this was by using the MailHelper static functions like this:
var client = new SendGridClient(HttpClient, new SendGridClientOptions { ApiKey = _sendGridApiKey, HttpErrorAsException = true });
SendGridMessage mailMsg;
var recipients = to.Split(',').Select((email) => new EmailAddress(email)).ToList();
if (recipients.Count() > 1)
{
mailMsg = MailHelper.CreateSingleEmailToMultipleRecipients(
new EmailAddress(from),
recipients,
subject,
"",
body);
}
else
{
mailMsg = MailHelper.CreateSingleEmail(
new EmailAddress(from),
recipients.First(),
subject,
"",
body);
}
if (attachment != null)
{
mailMsg.AddAttachment(attachment.Name,
attachment.ContentStream.ToBase64(),
attachment.ContentType.MediaType);
}
var response = await client.SendEmailAsync(mailMsg).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
_log.Trace($"'{subject}' email to '{to}' queued");
return true;
}
else {
throw new HttpRequestException($"'{subject}' email to '{to}' not queued");
}
I'm not sure why you wouldn't recieve any errors at your FROM address, but your JSON contains the following flaws:
, near the end makes the string invalid json
spaces around the first % in %name%, that might make sendgrid think it's an invalid substitution tag
if you use the X-SMTPAPI header to specify multiple recipients, you are not supposed to add a standard SMTP TO using AddTo().
Besides that, you didn't wrap the header at 72 characters (see the example in the documentation).
I figured that however the X-SMTPAPI documentation talks about passing the header as JSON, the API itself expects it as a parameter, containing Ienumerable string. So the working code is:
var myMessage3 = new SendGridMessage();
myMessage3.From = new MailAddress("email4#email.com", "Test Sender");
myMessage3.AddTo("email2#email.com");
myMessage3.Subject = "Új klubkártya regisztrálva";
myMessage3.Html = "Teszt üzenet";
myMessage3.EnableClickTracking(true);
/* SMTP API
* ===================================================*/
// Recipients
var addresses = new[]{
"email2#email.com", "email3#email.com"
};
//string check = string.Join(",", addresses);
myMessage3.Header.SetTo(addresses);
// Create credentials, specifying your user name and password.
var credentials = new NetworkCredential(ConfigurationManager.AppSettings["xxxxxxx"], ConfigurationManager.AppSettings["xxxxxxxxx"]);
// Create an Web transport for sending email.
var transportWeb = new Web(credentials);
// Send the email, which returns an awaitable task.
transportWeb.DeliverAsync(myMessage3);

How to convert EmailMessage alternate views into SendGrid Html and Text

I have an interface for sending mails
public interface IMailSender
{
void SendMail(MailMessage message);
}
When I create a mail I use AlternateView for that (plain text and html)
And now I would like to create a SendGridMailSender class that implements that interface, but my problem is that I don't know how to I populate the SendGrid.Html and SendGrid.Text based on the MailMessage. The only solution I could find means using a StreamReader and accesing the AlternateViewsCollection by index, I would like to thing there's a better solution that I can't figure out.
public void SendMail(MailMessage message)
{
var sendGridMessage = CreateSendGridMessage(message);
// Create network credentials to access your SendGrid account.
var user = "userCredential";
var pswd = "userPaswd";
var credentials = new NetworkCredential(user, pswd);
// Create an SMTP transport for sending email.
var transportSMTP = SMTP.GetInstance(credentials);
// Send the email.
transportSMTP.Deliver(sendGridMessage);
}
private SendGrid CreateSendGridMessage(MailMessage mail)
{
var sendGridMessage = SendGrid.GetInstance();
sendGridMessage.From = mail.From;
var recipients = mail.To;
foreach (var recipient in recipients)
{
sendGridMessage.AddTo(recipient.ToString());
}
var stream = mail.AlternateViews[0].ContentStream;
using (var reader = new StreamReader(stream))
{
sendGridMessage.Text = reader.ReadToEnd();
}
stream = mail.AlternateViews[1].ContentStream;
using (var reader = new StreamReader(stream))
{
sendGridMessage.Html = reader.ReadToEnd();
}
return sendGridMessage;
}
Thanks
The only way to access the AlternateView content is through the stream, so your solution is correct, although you should also check the ContentType to ensure that mail.AlternateViews[0] is in fact your Text part and so on.
Have you thought about using the official C# library instead? It makes it super simple to do what you're trying to do
// Create the email object first, then add the properties.
var myMessage = SendGrid.GetInstance();
// Add the message properties.
myMessage.From = new MailAddress("john#example.com");
// Add multiple addresses to the To field.
List<String> recipients = new List<String>
{
#"Jeff Smith <jeff#example.com>",
#"Anna Lidman <anna#example.com>",
#"Peter Saddow <peter#example.com>"
};
myMessage.AddTo(recipients);
myMessage.Subject = "Testing the SendGrid Library";
//Add the HTML and Text bodies
myMessage.Html = "<p>Hello World!</p>";
myMessage.Text = "Hello World plain text!";
https://github.com/sendgrid/sendgrid-csharp

HTML based email not working properly in asp.net web form

I am working on web form which collects certain user information from users and sends confirmation by email. I am trying to user the following approach to send the HTML email as it make managing HTML based email easy.
https://gist.github.com/1668751
I made necessary changes to the code but it is not working. I read other related article to make it work but i am doing something wrong.
Following line of code generates error The replacements dictionary must contain only strings.
MailMessage msgHtml = mailDef.CreateMailMessage(to, replacements, MessageBody, new System.Web.UI.Control());
I have made many change to the code but it doesnt seem to work for me. I would appreciate help to make this code work.
If i comment the above line of code with some other changes then i can send email but i can't replace the token. Any easy approach to replace token is also welcome.
Below is the Complete code i am using right now
String to, subject, Name;
subject = "Booking Confirmation";
Name = txtName.text;
ListDictionary replacements = new ListDictionary();
replacements.Add("<%Name%>", Name);
replacements.Add("<%Email%>", objVR.Email);
replacements.Add("<%CompanyName%>", objVR.CompanyName);
replacements.Add("<%BookingDate%>", objVR.BookingDate);
replacements.Add("<%BookingTime%>", objVR.TimeSlot);
replacements.Add("<%NoOfVisitors%>", objVR.NoOfVisitors);
replacements.Add("<%BookingCode%>", objVR.BookingUniqueID);
MailDefinition mailDef = new MailDefinition();
string MessageBody = String.Empty;
string filePath = System.Web.HttpContext.Current.Request.PhysicalApplicationPath;
using (StreamReader sr = new StreamReader(filePath + #"\en\VREmailEnglish.htm"))
{
MessageBody = sr.ReadToEnd();
}
MailMessage msgHtml = mailDef.CreateMailMessage(to, replacements, MessageBody, new System.Web.UI.Control());
string message = msgHtml.Body.ToString();
Helper.SendTokenEmail(to, subject, msgHtml, isHtml);
public static void SendTokenEmail(string to, string subject, string mailMessage, bool isHtml)
{
try
{
// Create a new message
var mail = new MailMessage();
// Set the to and from addresses.
mail.From = new MailAddress("noreply#somedomain.net");
mail.To.Add(new MailAddress(to));
// Define the message
mail.Subject = subject;
mail.IsBodyHtml = isHtml;
mail.Body = mailMessage.ToString();
//Object userState = mailMessage;
// Create a new Smpt Client using Google's servers
var mailclient = new SmtpClient();
mailclient.Host = "mail.XYZ.net";
//mailclient.Port = 587; //ForGmail
mailclient.Port = 2525;
mailclient.EnableSsl = false;
mailclient.UseDefaultCredentials = true;
// Specify your authentication details
mailclient.Credentials = new System.Net.NetworkCredential("noreply#somedomain.net", "XYZPassword");
mailclient.Send(mail);
mailclient.Dispose();
}
catch (Exception ex)
{
}
}
As pointed out by HatSoft the ListDictionary accepts objects as key and value so this looks like it should work.
But reading the docs for the CreateMailMessage() method here http://msdn.microsoft.com/en-us/library/0002kwb2.aspx indicates you need to convert the value to a string otherwise it will throw an ArgumentException.
So to fix make sure all values you add to the ListDictionary are converted to string i.e
objVR.BookingDate.ToString()

.IsBodyHtml=true causes an empty email body to be sent, but .IsBodyHtml=false sends the body content

I have a WCF service that sends email based on user input. It was brought to my attention that, recently, a particular user's email were being delivered without any body text. If .IsBodyHtml is set to true, no body text is transferred; but, if .IsBodyHtml is set to false, the body has the appropriate text. However, it doesn't seem to be consistent, as it seems to occur only when said user's email address is set as the "From" address.Tech Details:We have an MS Exchange mail server. I'm composing a MailMessage object passing it to the built-in SMTP class to send the message.
The code has been simplified, a bit, for brevity/clarity. Nevertheless, the original code is pretty standard/straight-forward. email refers to a LINQ-to-SQL class object
MailMessage message = new MailMessage();
message.From = new MailAddress(email.fromAddress);
message.To.Add(email.toRecipient);
message.Subject = email.emailSubject;
//set email body
message.IsBodyHtml = true;
message.Body = email.emailBody;
Attachment attachmentFile = null;
if (email.hasAttachment == true)
{
//retrieve attachments for emailID
var attachments = from attach in db.EmailAttachments
where attach.emailID == emailID
select attach;
foreach (var attachment in attachments)
{//attach each attachment
string filePath = Path.Combine(UPLOAD_DIRECTORY, emailID.ToString(), attachment.fileName);
attachmentFile = new Attachment(filePath);
message.Attachments.Add(attachmentFile); //set attachment from input path
}
}
SmtpClient client = new SmtpClient(SMTP_SERVER, SMTP_PORT); //set SMTP server name/URL and port
client.Send(message); //try to send the SMTP email
Since the problem relates to a user, it is probably related to the setting of this user.
Log in as that user and open outlook
Select: File -> Options -> Mail
Scroll down to the section "Message Format"
Probably "Convert to PlainText Format is selected" change this to "Convert to HTML Format"

Categories