I am trying to attach a file in the AWS ses email. The file is being received by HttpPostedFileBase but the problem is I have no idea how can I use it to attach in a method called GetMessageBody() because body.Attachments.Add() only takes input for file location, not the HttpPostedFileBase file. Any idea how can I attach the file received by HttpPostedFileBase?
Use case:
[HttpPost, ValidateInput(false)]
public ActionResult SendHtmlEmailWithAttachment(HttpPostedFileBase file)
{
AWSEmailWithAttachment.SendAttachmentEmails("test#gmail.com", "noreply#test.co.uk", "my subject", file);
return Json("ok");
}
AWS ses email class:
public class AWSEmailWithAttachment
{
private static BodyBuilder GetMessageBody(HttpPostedFileBase attachment)
{
var body = new BodyBuilder()
{
HtmlBody = #"<p>Amazon SES Test body</p>",
TextBody = "Amazon SES Test body",
};
body.Attachments.Add(#"C:\Users\liaka\OneDrive\Desktop\attachment.txt");//I can use file location to attach with email but no idea how can i take file input form HttpPostedFileBase
return body;
}
private static MimeMessage GetMessage(string receiveraddress, string senderaddress, string subject, HttpPostedFileBase attachment)
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Foo Bar", senderaddress));
message.To.Add(new MailboxAddress(string.Empty, receiveraddress));
message.Subject = subject;
message.Body = GetMessageBody(attachment).ToMessageBody();
return message;
}
private static MemoryStream GetMessageStream(string receiveraddress, string senderaddress, string subject, HttpPostedFileBase attachment)
{
var stream = new MemoryStream();
GetMessage(receiveraddress, senderaddress, subject, attachment).WriteTo(stream);
return stream;
}
public static void SendAttachmentEmails(string receiveraddress, string senderaddress, string subject, HttpPostedFileBase attachment)
{
var credentals = new BasicAWSCredentials(Credentials.AWS_Access_Key_ID, Credentials.AWS_Secret_Access_Key);
using (var client = new AmazonSimpleEmailServiceClient(credentals, RegionEndpoint.EUWest2))
{
var sendRequest = new SendRawEmailRequest { RawMessage = new RawMessage(GetMessageStream(receiveraddress, senderaddress, subject, attachment)) };
try
{
var response = client.SendRawEmail(sendRequest);
}
catch (Exception e) { }
}
}
}
Related
By using VS 2017, I created a SSIS package and then tried to utilize SendGrid with Script Task component but I kept have error messages. Error message is "Exception has been thrown by the target of an invocation." The following is my code and please help me look at what's wrong with it. Thank you.
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
static EmailAddress yao = new EmailAddress("user#sample.com", "User Sample");
static string template_id = "SendGridTemplateID";
static string _api_key = ConfigurationManager.AppSettings["SendGridKey"];
public void Main()
{
SendEmail().Wait();
Dts.TaskResult = (int)ScriptResults.Success;
}
static async Task SendEmail()
{
var client = new SendGridClient(_api_key);
var msg = new SendGridMessage();
msg.AddTo(new EmailAddress("Sample#user.com", "Sample User"));
msg.SetFrom(new EmailAddress("Sample#user.com", "Sample User"));
msg.SetTemplateData(GoogleLinkReport);
msg.SetTemplateId(template_id);
var response = await client.SendEmailAsync(msg);
Console.WriteLine(response.Body.ReadAsStringAsync().Result);
}
static GoogleLink GoogleLinkReport = new GoogleLink
{
header = "This is google link",
text = "Please click the button to open the link for google",
subject = "GoogleLink",
c2a_link = "https://www.google.com",
c2a_button = "Google Link"
};
public class GoogleLink
{
public string header;
public string text;
public string subject;
public string c2a_link;
public string c2a_button;
}
}
I am trying to send chars like : / . in asp.net mvc 5 to an API controller endpoint, but it fails as soon as I try something containing certain chars. For example, I can't send message:hi, I have to change it to message_hi to get it working.
I am trying to send an email using Exchange and the body (containing an URL and other info) won't go through.
My API Controller:
[Route("send/{adress}/{subject}/{body}")]
public void SendEmail(string adress, string subject, string body)
{
Office365MailSender ms = new Office365MailSender();
EmailDto email = new EmailDto(adress, subject, body);
ms.Send(email);
}
Calling the above endpoint from my application:
public static async Task<string> SendMail(IPhoneCall phoneCall)
{
var email = new EmailEntity(phoneCall);
using (var client = new HttpClient())
{
var uri = new Uri("http://url/email/send/" + email.Recipient + "/" + email.Title + "/" + email.body);
var msg = await client.GetAsync(uri);
}
return "Email Sent";
}
An example of a value of the uri variable would be:
http://url/email/send/myemail#outlook.com/Hello There/Hi,\nThis is a url you can use for stuff: https://thisisit.com. \n Thanks bye.
I've tried HttpUtility.UrlEncode on the body before I send it, but that does nothing. Does anyone know how to send strings containing these type of chars?
I would recommend you using the POST verb in order to send the body of the message. So you could start by writing a view model:
public class MailMessageViewModel
{
public string Address { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
}
that your Web API action will take as parameter:
[Route("send")]
[HttpPost]
public IHttpActionResult SendEmail(MyViewModel model)
{
Office365MailSender ms = new Office365MailSender();
EmailDto email = new EmailDto(model.Address, model.Subject, model.Body);
ms.Send(email);
return this.Ok();
}
and then you could invoke like this:
var email = new EmailEntity(phoneCall);
using (var client = new HttpClient())
{
var uri = new Uri("http://url/email/send");
var content = new StringContent(
JsonConvert.SerializeObject(new
{
Address = email.Recipient,
Subject = email.Title,
Body = email.body,
}),
UnicodeEncoding.UTF8,
"application/json");
var msg = await client.PostAsync(uri, content);
}
I've successfully created custom email service provider for UserManager by extending IIdentityMessageService:
public class ExchangeEmailService : IIdentityMessageService
{
public async Task SendAsync(IdentityMessage message)
{
using (var client = new SmtpClient())
{
client.Host = "mail.example.com";
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(#"noreply", "P#ssw0rd");
var from = new MailAddress("no-reply#example.com");
var to = new MailAddress(message.Destination);
var mailMessage = new MailMessage(from, to)
{
Subject = message.Subject,
Body = message.Body,
IsBodyHtml = true
};
await client.SendMailAsync(mailMessage);
}
}
}
Inside UserManager's Create I'm creating new instance of my service and assigning it to EmailService:
userManager.EmailService = new ExchangeEmailService();
This all works fine, but I have requirement to send emails from different email addresses, based on place this is called from, unfortunately UserManager.SendEmailAsync isn't allowing me to pass anything except userId, subject and body.
Ideally I'd like to be able to specify email address when calling SendEmailAcync or enum value.
I've searched in UserManager source and I thought about creating custom SendEmailAsync implementation, but I'd have to change multiple places - IIdentityMessageService, UserManager.
I know I can create new interface and build my email sending class on it, but I'd like to keep changes to minimum.
What I'd like to get:
I'd like to have enum containing names of mailboxes:
public enum Mailboxes
{
Noreply = 0,
Service = 1,
Contact = 2
}
and be able to call SendEmailAsync with that additional parameter:
await UserManager.SendEmailAsync(user.Id, "Account created", "Nice email content.", Mailboxes.Noreply );
I'm aware that I can set different title and use same email address, but this is requirement I got.
How can I do that?
A hack would be to create a model to store what you want sent to the service
public class MessageBody {
public string Body { get; set; }
public MailBoxes Source { get; set; }
}
and then serialize it (JSON maybe) as the body parameter of the SendEmailAsync method call.
var message = new MessageBody {
Body = "Nice email content.",
Source = Mailboxes.Noreply
};
var body = JsonConvert.SerializeObject(message);
await UserManager.SendEmailAsync(user.Id, "Account created", body);
The service would then deserialize the model, construct the email with the custom info and then send the email.
public class ExchangeEmailService : IIdentityMessageService {
readonly IMailBoxProvider provider;
public ExchangeEmailService(IMailBoxProvider provider) {
this.provider = provider;
}
public async Task SendAsync(IdentityMessage message) {
using (var client = new SmtpClient()) {
client.Host = "mail.example.com";
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential(#"noreply", "P#ssw0rd");
//Get the body and from address
var fromEmailAddress = "default-email#example.com";
var body = message.Body;
try {
var msg = JsonConvert.DeserializeObject<MessageBody>(body);
if(msg != null) {
body = msg.Body;
fromEmailAddress = provider.GetMailbox(msg.Source);
}
} catch { }
var from = new MailAddress(fromEmailAddress);
var to = new MailAddress(message.Destination);
var mailMessage = new MailMessage(from, to)
{
Subject = message.Subject,
Body = body,
IsBodyHtml = true
};
await client.SendMailAsync(mailMessage);
}
}
}
And just make sure to assigning it to UserManager.EmailService:
userManager.EmailService = new ExchangeEmailService(new MailBoxProvider());
I try send mail with my smtp client but i dont have exception and mail doesn't recieved.
public void SendSMTPMail(string from, string to, string subject, string body)
{
var smtp_client = new SmtpClient("mail.mydomain.gr",25);
smtp_client.UseDefaultCredentials = false;
smtp_client.EnableSsl = false;
smtp_client.Credentials = new NetworkCredential("noreply#mydomain.gr", "mypass");
ServicePointManager.ServerCertificateValidationCallback = (s, certificate, chain, sslPolicyErrors) => true;
var msg = new MailMessage(from, to );
msg.Subject = subject;
msg.Body = body;
smtp_client.SendAsync(msg , string.Empty);
}
i use breakpoint and i find some info
smtp_client.ServicePoint System.NotImplementException: The request feature is not implemented
but i use this code with another smtp and works fine. Any help ?
As an alternative, you could use my MailKit library to send mail using Xamarin.iOS/Android/Mac.
public void SendSMTPMail(string from, string to, string subject, string body)
{
var message = new MimeMessage ();
var builder = new BodyBuilder ();
message.From.Add (InternetAddress.Parse (from));
message.To.Add (InternetAddress.Parse (to));
message.Subject = subject;
builder.TextBody = body;
message.Body = builder.ToMessageBody ();
using (var client = new SmtpClient ()) {
client.ServerCertificateValidationCallback = (s, certificate, chain, sslPolicyErrors) => true;
client.Connect ("mail.mydomain.gr", 25, false);
client.Authenticate ("noreply#mydomain.gr", "mypass");
client.Send (message);
client.Disconnect (true);
}
}
It seems like you can't use the System.Net.Mail.SmtpClient in Xamarin.
Instead you should use the the mail service with native implementation. Tiny example here. The Forms code:
public abstract class EmailService
{
public static readonly Lazy<EmailService> Instance = new Lazy<EmailService>(() => DependencyService.Get<EmailService>());
public abstract bool CanSend { get; }
public abstract void ShowDraft(string subject, string body, bool html, string to, byte[] screenshot = null);
public abstract void ShowDraft(string subject, string body, bool html, string[] to, string[] cc, string[] bcc, byte[] screenshot = null);
}
The native iOS code:
public class EmailServiceIos : EmailService
{
public override bool CanSend
{
get
{
return MFMailComposeViewController.CanSendMail;
}
}
public override void ShowDraft(
string subject,
string body,
bool html,
string[] to,
string[] cc,
string[] bcc,
byte[] screenshot = null)
{
var mailer = new MFMailComposeViewController();
mailer.SetMessageBody(body ?? string.Empty, html);
mailer.SetSubject(subject ?? string.Empty);
mailer.SetCcRecipients(cc);
mailer.SetToRecipients(to);
mailer.Finished += (s, e) => ((MFMailComposeViewController)s).DismissViewController(true, () => { });
if (screenshot != null)
{
mailer.AddAttachmentData(NSData.FromArray(screenshot), "image/png", "screenshot.png");
}
UIViewController vc = UIApplication.SharedApplication.KeyWindow.RootViewController;
while (vc.PresentedViewController != null)
{
vc = vc.PresentedViewController;
}
vc.PresentViewController(mailer, true, null);
}
public override void ShowDraft(string subject, string body, bool html, string to, byte[] screenshot = null)
{
this.ShowDraft(subject, body, html, new[] { to }, new string[] { }, new string[] { }, screenshot);
}
}
And invoke the whole thing from the Forms code like:
var emailService = DependencyService.Get<EmailService>();
if (emailService.CanSend)
{
emailService.ShowDraft(
"Your caption",
"Your text",
true,
"your#ddress.com");
}
I´m using Asp.Net-Identity-2 to manage user access in my app.
I´m using EmailService (UserManager.SendEmail) to send confirmation email messages and I´d like to send a formatted HTML message, and I want attach images in it.
How can I do that??
Setup Identity User Manager EmailService
public class AppUserManager : UserManager<AppUser>
{
public AppUserManager(IUserStore<AppUser> store) : base(store) { }
public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context)
{
AppUserManager manager = new AppUserManager(new UserStore<AppUser>(db));
//Some setup code here ....
//Hook to my EmailService (see class MyEmailService.cs)
manager.EmailService = new MyEmailService();
return manager;
} //Create
} //class
MyEmailService
public class MyEmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
MailMessage email = new MailMessage("me#sample.com", message.Destination);
email.Subject = message.Subject;
email.Body = message.Body;
email.IsBodyHtml = true;
var mailClient = new SmtpClient();
mailClient.Host = "EmailServer";
mailClient.Port = 25;
return mailClient.SendMailAsync(email);
} //SendAsync
} //class
Action to send email
public ActionResult ForgotPassword(string email)
{
if (ModelState.IsValid)
{
AppUser user = UserManager.FindByEmail(email);
if (user == null || !(UserManager.IsEmailConfirmed(user.Id)))
{
return View("../Home/Index");
} //if
string code = UserManager.GenerateEmailConfirmationToken(user.Id);
string callbackUrl = Url.Action("ResetPassword", "Admin", new { Id = user.Id, code = code }, protocol: Request.Url.Scheme);
string strMessage = getHTMLMessage(); //variable Html message here, with images references in it (ex. "<img src='cid:IMAGE_TITLE'>")
UserManager.SendEmail(user.Id, "Message Subject", strMessage);
return View("../Home/Index");
}
// If we got this far, something failed, redisplay form
return View();
} //ForgotPassword
My doubt is how to attach images in that message...
Thanks for any help..
Julio Schurt
I had to create another method in my service and call it directly
public Task SendAsync(IdentityMessage message, IEnumerable<KeyValuePair<string, Stream>> attach)
{
var myMessage = new SendGridMessage() { From = new MailAddress("my#email.com") };
myMessage.AddTo(message.Destination);
myMessage.Subject = message.Subject;
myMessage.Html = message.Body;
myMessage.Text = message.Body;
var credentials = new NetworkCredential("myuser", "mypassword");
var transportWeb = new Web(credentials);
foreach (var file in attach)
{
myMessage.AddAttachment(file.Value,file.Key);
}
return transportWeb.DeliverAsync(myMessage);
}
EDIT: (2015-08-14)
Final class:
public class EmailService : IIdentityMessageService
{
const string from = "mail#domain.com";
const string username = "username";//Environment.GetEnvironmentVariable("SENDGRID_USER");
const string pswd = "password";//Environment.GetEnvironmentVariable("SENDGRID_PASS");
private List<KeyValuePair<string, Stream>> _attachments;
private List<KeyValuePair<string, string>> _recipients;
public Task SendAsync(IdentityMessage message)
{
var myMessage = new SendGridMessage() { From = new MailAddress(from) };
var credentials = new NetworkCredential(username, pswd);
var transportWeb = new Web(credentials);
myMessage.AddTo(message.Destination);
if (_recipients != null)
{
_recipients.ForEach(r => myMessage.AddTo(string.Format("{0} {1}", r.Key, r.Value)));
}
myMessage.Subject = message.Subject;
myMessage.Html = message.Body;
myMessage.Text = message.Body;
if (_attachments != null)
{
foreach (var attachment in _attachments)
{
myMessage.AddAttachment(attachment.Value, attachment.Key);
}
}
return transportWeb.DeliverAsync(myMessage);
}
public Task SendAsync(IdentityMessage message, IEnumerable<KeyValuePair<string, Stream>> attachments)
{
var myMessage = new SendGridMessage() { From = new MailAddress(from) };
var credentials = new NetworkCredential(username, pswd);
var transportWeb = new Web(credentials);
myMessage.AddTo(message.Destination);
myMessage.Subject = message.Subject;
myMessage.Html = message.Body;
myMessage.Text = message.Body;
foreach (var attachment in attachments)
{
myMessage.AddAttachment(attachment.Value, attachment.Key);
}
return transportWeb.DeliverAsync(myMessage);
}
public Task SendAsync(IdentityMessage message, KeyValuePair<string, Stream> attachment)
{
var myMessage = new SendGridMessage() { From = new MailAddress(from) };
var credentials = new NetworkCredential(username, pswd);
var transportWeb = new Web(credentials);
myMessage.AddTo(message.Destination);
myMessage.Subject = message.Subject;
myMessage.Html = message.Body;
myMessage.Text = message.Body;
myMessage.AddAttachment(attachment.Value, attachment.Key);
return transportWeb.DeliverAsync(myMessage);
}
public void AddTo(string name,string mail)
{
_recipients = _recipients ?? new List<KeyValuePair<string, string>>();
_recipients.Add(new KeyValuePair<string, string>(name, string.Format("<{0}>", mail)));
}
public void AddAttachment(string name, Stream file)
{
_attachments = _attachments ?? new List<KeyValuePair<string, Stream>>();
_attachments.Add(new KeyValuePair<string, Stream>(name, file));
}
public void AddAttachment<T>(string name, T records)
{
var jsonSerialiser = new JavaScriptSerializer();
var json = jsonSerialiser.Serialize(records);
var bytes = Encoding.UTF8.GetBytes(json);
var ms = new MemoryStream(bytes);
ms.Flush();
ms.Seek(0, SeekOrigin.Begin);
_attachments = _attachments ?? new List<KeyValuePair<string, Stream>>();
_attachments.Add(new KeyValuePair<string, Stream>(name, ms));
}
}
Then can use it...
// use it directly
var emailService = new EmailService();
IdentityMessage msg = new IdentityMessage()
{
Destination = "test <test#domain.com>",
Subject = "Subject",
Body = "Body"
};
emailService.AddTo("Name1", "mail1#domain.com");
emailService.AddTo("Name2", "mail2#domain.com");
emailService.AddTo("Name3", "mail3#domaincom");
emailService.AddAttachment(filename", stream);
await emailService.SendAsync(msg);
// Or use it from UserManager
(UserManager.EmailService as EmailService).AddAttachment("name", yourStream);
await UserManager.SendEmailAsync("userid", "subject", "body");