c# - mail - Enviar adjuntos con Amazon-SES
smtpclient c# (7)
Estoy buscando un ejemplo de C # funcional para enviar archivos adjuntos con Amazon-SES.
Después de leer que Amazon-SES ahora admite el envío de archivos adjuntos, estaba buscando un ejemplo de C # pero no pude encontrar uno.
Creo que necesitas seguir las instrucciones en este enlace . Amazon no le permite agregar archivos adjuntos u otros tipos de mensajes más complicados (eventos iCalendar). Esencialmente, debe crear el cuerpo del mensaje de forma manual mediante la construcción de cadenas y la manipulación.
Actualmente hago esto para los correos electrónicos en formato iCalendar en un sistema heredado. Es un poco molesto, pero si lees RFC 2822, te dice con bastante claridad cuál es el formato. Cosas especiales para prestar atención a:
- Codificación Base64 de los datos.
- Tipos mime
- Asegúrese de que sus límites de varias partes coincidan (y sean únicos)
- Problemas complicados con el número de saltos de línea (/ n) después de ciertas líneas
La mejor de las suertes. No sé si hay una biblioteca abierta que haga este tipo de cosas para usted en C #. Si puede encontrar uno, intente usarlo, ya que lidiar con las complejidades de la RFC debe tener un aviso médico para el aumento de la presión arterial y la pérdida de cabello.
Creo que usar AWS SDK para .NET y MimeKit es una solución muy fácil y limpia. Puede enviar correos electrónicos con archivos adjuntos a través de SES API (en lugar de SMTP).
Puede escribir MimeMessage directamente en MemoryStream y luego usarlo con SES SendRawEmail:
using Amazon.SimpleEmail;
using Amazon.SimpleEmail.Model;
using Amazon;
using Amazon.Runtime;
using MimeKit;
private static BodyBuilder GetMessageBody()
{
var body = new BodyBuilder()
{
HtmlBody = @"<p>Amazon SES Test body</p>",
TextBody = "Amazon SES Test body",
};
body.Attachments.Add(@"c:/attachment.txt");
return body;
}
private static MimeMessage GetMessage()
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Foo Bar", "[email protected]"));
message.To.Add(new MailboxAddress(string.Empty, "[email protected]"));
message.Subject = "Amazon SES Test";
message.Body = GetMessageBody().ToMessageBody();
return message;
}
private static MemoryStream GetMessageStream()
{
var stream = new MemoryStream();
GetMessage().WriteTo(stream);
return stream;
}
private void SendEmails()
{
var credentals = new BasicAWSCredentials("<aws-access-key>", "<aws-secret-key>");
using (var client = new AmazonSimpleEmailServiceClient(credentals, RegionEndpoint.EUWest1))
{
var sendRequest = new SendRawEmailRequest { RawMessage = new RawMessage(GetMessageStream()) };
try
{
var response = client.SendRawEmail(sendRequest);
Console.WriteLine("The email was sent successfully.");
}
catch (Exception e)
{
Console.WriteLine("The email was not sent.");
Console.WriteLine("Error message: " + e.Message);
}
}
}
Esta es una implementación muy simple usando MimeKit
using Amazon;
using Amazon.SimpleEmail;
using Amazon.SimpleEmail.Model;
using MimeKit;
using System.IO;
namespace SendEmailWithAttachments
{
class Program
{
static void Main(string[] args)
{
//Remember to enter your (AWSAccessKeyID, AWSSecretAccessKey) if not using and IAM User with credentials assigned to your instance and your RegionEndpoint
using (var client = new AmazonSimpleEmailServiceClient("YourAWSAccessKeyID", "YourAWSSecretAccessKey", RegionEndpoint.USEast1))
using (var messageStream = new MemoryStream())
{
var message = new MimeMessage();
var builder = new BodyBuilder() { TextBody = "Hello World" };
message.From.Add(new MailboxAddress("[email protected]"));
message.To.Add(new MailboxAddress("[email protected]"));
message.Subject = "Hello World";
//I''m using the stream method, but you don''t have to.
using (FileStream stream = File.Open(@"Attachment1.pdf", FileMode.Open)) builder.Attachments.Add("Attachment1.pdf", stream);
using (FileStream stream = File.Open(@"Attachment2.pdf", FileMode.Open)) builder.Attachments.Add("Attachment2.pdf", stream);
message.Body = builder.ToMessageBody();
message.WriteTo(messageStream);
var request = new SendRawEmailRequest()
{
RawMessage = new RawMessage() { Data = messageStream }
};
client.SendRawEmail(request);
}
}
}
}
Tengo el código en mi repositorio https://github.com/gianluis90/amazon-send-email
No estoy seguro de si esto es lo que está buscando, pero es el único recurso que he podido encontrar sobre el tema. Me encantaría una mejor respuesta a esta pregunta, también.
http://docs.amazonwebservices.com/ses/latest/DeveloperGuide/
Declara cómo usarlo, pero es muy críptico, al menos para mí.
¿Alguna guía mejor por ahí?
También necesito ayuda con esto, pero hasta ahora he encontrado que necesitas enviar un mensaje MIME de varias partes, con el archivo adjunto codificado en base64.
También puede configurar IIS SMTP para retransmitir a través de SES.
Necesitas instalar stunnel y configurarlo
Luego, solo puede configurar el SMTP Smart Host de IIS y algunas otras opciones, y transmitirá su correo electrónico a través de SES.
Instrucciones de la esencia enlazada arriba:
Instrucciones tomadas de los documentos de Amazon y modificadas según sea necesario.
1. Instalar stunnel :
- Descargar desde la stunnel de stunnel
- Ejecute el instalador con las opciones predeterminadas, cree un certificado autofirmado respondiendo las preguntas
- Abra el
c:/program files (x86)/stunnel/stunnel.conf
en el bloc de notas - Borre todas las configuraciones del servidor (en la sección
Example SSL server mode services
, no tendrá una líneaclient = yes
) - Crear una nueva configuración de cliente:
[smtp-tls-wrapper]
acepta = 127.0.0.1:2525
cliente = si
connect = email-smtp.us-east-1.amazonaws.com:465
- Inicie
stunnel.exe
y asegúrese de que no se informen errores (obtendrá un pequeño icono de la bandeja del sistema) - Si tiene éxito, opcionalmente puede instalarlo como un servicio, ejecutando
stunnel.exe -install
en la línea de comandos (tenga en cuenta que esto instala el servicio pero no lo inicia, así que comience) - Pruebe la conexión, en la línea cmd, ejecute
telnet localhost 2525
y verá una respuesta SMTP del servidor de Amazon (si telnet no está instalado, agregue la función en el Administrador del servidor / Características / Agregar función )
2. Configurar IIS SMTP
- Configure Smart Host como
[127.0.0.1]
(incluya los corchetes) - En la sección Conexiones de salida , establezca el puerto de salida en
2525
(como el archivo stunnel.conf) - En la sección Seguridad de salida , configure la información de autenticación para sus credenciales de SMTP de Amazon, configúrela a la autenticación básica ( NOTA: NO COMPRUEBE LA CAJA DE VERIFICACIÓN DE TLS)
public Boolean SendRawEmail(String from, String to, String cc, String Subject, String text, String html, String replyTo, string attachPath)
{
AlternateView plainView = AlternateView.CreateAlternateViewFromString(text, Encoding.UTF8, "text/plain");
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(html, Encoding.UTF8, "text/html");
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress(from);
List<String> toAddresses = to.Replace(", ", ",").Split('','').ToList();
foreach (String toAddress in toAddresses)
{
mailMessage.To.Add(new MailAddress(toAddress));
}
List<String> ccAddresses = cc.Replace(", ", ",").Split('','').Where(y => y != "").ToList();
foreach (String ccAddress in ccAddresses)
{
mailMessage.CC.Add(new MailAddress(ccAddress));
}
mailMessage.Subject = Subject;
mailMessage.SubjectEncoding = Encoding.UTF8;
if (replyTo != null)
{
mailMessage.ReplyToList.Add(new MailAddress(replyTo));
}
if (text != null)
{
mailMessage.AlternateViews.Add(plainView);
}
if (html != null)
{
mailMessage.AlternateViews.Add(htmlView);
}
if (attachPath.Trim() != "")
{
if (System.IO.File.Exists(attachPath))
{
System.Net.Mail.Attachment objAttach = new System.Net.Mail.Attachment(attachPath);
objAttach.ContentType = new ContentType("application/octet-stream");
System.Net.Mime.ContentDisposition disposition = objAttach.ContentDisposition;
disposition.DispositionType = "attachment";
disposition.CreationDate = System.IO.File.GetCreationTime(attachPath);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(attachPath);
disposition.ReadDate = System.IO.File.GetLastAccessTime(attachPath);
mailMessage.Attachments.Add(objAttach);
}
}
RawMessage rawMessage = new RawMessage();
using (MemoryStream memoryStream = ConvertMailMessageToMemoryStream(mailMessage))
{
rawMessage.WithData(memoryStream);
}
SendRawEmailRequest request = new SendRawEmailRequest();
request.WithRawMessage(rawMessage);
request.WithDestinations(toAddresses);
request.WithSource(from);
AmazonSimpleEmailService ses = AWSClientFactory.CreateAmazonSimpleEmailServiceClient(ConfigurationManager.AppSettings.Get("AccessKeyId"), ConfigurationManager.AppSettings.Get("SecretKeyId"));
try
{
SendRawEmailResponse response = ses.SendRawEmail(request);
SendRawEmailResult result = response.SendRawEmailResult;
return true;
}
catch (AmazonSimpleEmailServiceException ex)
{
return false;
}
}
public static MemoryStream ConvertMailMessageToMemoryStream(MailMessage message)
{
Assembly assembly = typeof(SmtpClient).Assembly;
Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
MemoryStream fileStream = new MemoryStream();
ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
object mailWriter = mailWriterContructor.Invoke(new object[] { fileStream });
MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true }, null);
MethodInfo closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic);
closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
return fileStream;
}
Encontrado que here
Actualización: la firma de un método ha cambiado en .NET 4.5, lo que rompe lo anterior: obtener System.Net.Mail.MailMessage como MemoryStream en .NET 4.5 beta