Agregar archivos de proyecto.
This commit is contained in:
5
Documentos/Enlaces.txt
Normal file
5
Documentos/Enlaces.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
https://www.exfabrica.io/en/blog/how-to-securely-send-emails-via-gmail-using-oauth2-in-csharp-dotnet-a-step-by-step-guide.html
|
||||||
|
https://stackoverflow.com/questions/73464501/sending-email-with-oauth2-and-smtp-gmail-c
|
||||||
|
https://github.com/SmartQPtyLtd/GmailOAuth
|
||||||
|
https://learn.microsoft.com/es-es/power-platform/admin/connect-gmail-oauth2?tabs=new
|
||||||
|
https://developers.google.com/identity/protocols/oauth2?hl=es-419
|
||||||
File diff suppressed because one or more lines are too long
207
GmailOAuthSender.cs
Normal file
207
GmailOAuthSender.cs
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
using MailKit.Net.Smtp;
|
||||||
|
using MailKit.Security;
|
||||||
|
using MimeKit;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Mail;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public static class GmailOAuthSender
|
||||||
|
{
|
||||||
|
public static async Task EnviarCorreoAsync(GmailConfig config,
|
||||||
|
string tokenOAuth,
|
||||||
|
string destinatarios,
|
||||||
|
string asunto,
|
||||||
|
string cuerpo,
|
||||||
|
bool cuerpoHtml = false,
|
||||||
|
string cc = "",
|
||||||
|
string bcc = "",
|
||||||
|
string responderA = "",
|
||||||
|
List<Attachment> adjuntos = null,
|
||||||
|
string servidorSMTP = "smtp.gmail.com",
|
||||||
|
int puerto = 587)
|
||||||
|
{
|
||||||
|
if (tokenOAuth=="") tokenOAuth = await GmailTokenManager.ObtenerAccessTokenAsync(config);
|
||||||
|
var mensaje = new MimeMessage();
|
||||||
|
mensaje.From.Add(new MailboxAddress(config.NombreRemitente ?? config.Remitente, config.Remitente));
|
||||||
|
|
||||||
|
foreach (var d in destinatarios.Split(';').Where(x => !string.IsNullOrWhiteSpace(x)))
|
||||||
|
mensaje.To.Add(new MailboxAddress(d.Trim(), d.Trim()));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(cc))
|
||||||
|
foreach (var c in cc.Split(';'))
|
||||||
|
mensaje.Cc.Add(new MailboxAddress(c.Trim(), c.Trim()));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(bcc))
|
||||||
|
foreach (var b in bcc.Split(';'))
|
||||||
|
mensaje.Bcc.Add(new MailboxAddress(b.Trim(), b.Trim()));
|
||||||
|
|
||||||
|
mensaje.ReplyTo.Add(new MailboxAddress(string.IsNullOrWhiteSpace(responderA) ? config.NombreRemitente : responderA,
|
||||||
|
string.IsNullOrWhiteSpace(responderA) ? config.Remitente : responderA));
|
||||||
|
|
||||||
|
mensaje.Subject = asunto.Replace("\r", "").Replace("\n", " ");
|
||||||
|
|
||||||
|
var builder = new BodyBuilder
|
||||||
|
{
|
||||||
|
HtmlBody = cuerpoHtml ? cuerpo : null,
|
||||||
|
TextBody = cuerpoHtml ? null : cuerpo
|
||||||
|
};
|
||||||
|
|
||||||
|
if (adjuntos != null)
|
||||||
|
{
|
||||||
|
foreach (var att in adjuntos)
|
||||||
|
{
|
||||||
|
var ms = new MemoryStream();
|
||||||
|
att.ContentStream.CopyTo(ms);
|
||||||
|
builder.Attachments.Add(att.Name, ms.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mensaje.Body = builder.ToMessageBody();
|
||||||
|
|
||||||
|
var cliente = new MailKit.Net.Smtp.SmtpClient();
|
||||||
|
cliente.ServerCertificateValidationCallback = (s, c, ch, e) => true;
|
||||||
|
|
||||||
|
await cliente.ConnectAsync(servidorSMTP, puerto, SecureSocketOptions.StartTls);
|
||||||
|
await cliente.AuthenticateAsync(new SaslMechanismOAuth2(config.Remitente, tokenOAuth));
|
||||||
|
await cliente.SendAsync(mensaje);
|
||||||
|
await cliente.DisconnectAsync(true);
|
||||||
|
}
|
||||||
|
public static async Task EnviarCorreoALAsync(GmailConfig config,
|
||||||
|
string tokenOAuth,
|
||||||
|
string destinatarios,
|
||||||
|
string asunto,
|
||||||
|
string cuerpo,
|
||||||
|
bool cuerpoHtml = false,
|
||||||
|
string cc = "",
|
||||||
|
string bcc = "",
|
||||||
|
string responderA = "",
|
||||||
|
ArrayList adjuntos = null,
|
||||||
|
string servidorSMTP = "smtp.gmail.com",
|
||||||
|
int puerto = 587)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(tokenOAuth))
|
||||||
|
tokenOAuth = await GmailTokenManager.ObtenerAccessTokenAsync(config);
|
||||||
|
|
||||||
|
var mensaje = new MimeMessage();
|
||||||
|
mensaje.From.Add(new MailboxAddress(config.NombreRemitente ?? config.Remitente, config.Remitente));
|
||||||
|
|
||||||
|
foreach (var d in destinatarios.Split(';').Where(x => !string.IsNullOrWhiteSpace(x)))
|
||||||
|
mensaje.To.Add(new MailboxAddress(d.Trim(), d.Trim()));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(cc))
|
||||||
|
foreach (var c in cc.Split(';'))
|
||||||
|
mensaje.Cc.Add(new MailboxAddress(c.Trim(), c.Trim()));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(bcc))
|
||||||
|
foreach (var b in bcc.Split(';'))
|
||||||
|
mensaje.Bcc.Add(new MailboxAddress(b.Trim(), b.Trim()));
|
||||||
|
|
||||||
|
mensaje.ReplyTo.Add(new MailboxAddress(
|
||||||
|
string.IsNullOrWhiteSpace(responderA) ? config.NombreRemitente : responderA,
|
||||||
|
string.IsNullOrWhiteSpace(responderA) ? config.Remitente : responderA));
|
||||||
|
|
||||||
|
mensaje.Subject = asunto.Replace("\r", "").Replace("\n", " ");
|
||||||
|
|
||||||
|
var builder = new BodyBuilder
|
||||||
|
{
|
||||||
|
HtmlBody = cuerpoHtml ? cuerpo : null,
|
||||||
|
TextBody = cuerpoHtml ? null : cuerpo
|
||||||
|
};
|
||||||
|
|
||||||
|
if (adjuntos != null)
|
||||||
|
{
|
||||||
|
foreach (var item in adjuntos)
|
||||||
|
{
|
||||||
|
if (item is Attachment att)
|
||||||
|
{
|
||||||
|
var ms = new MemoryStream();
|
||||||
|
att.ContentStream.CopyTo(ms);
|
||||||
|
builder.Attachments.Add(att.Name, ms.ToArray());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidCastException("El objeto en adjuntos no es de tipo Attachment.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mensaje.Body = builder.ToMessageBody();
|
||||||
|
|
||||||
|
var cliente = new MailKit.Net.Smtp.SmtpClient();
|
||||||
|
cliente.ServerCertificateValidationCallback = (s, c, ch, e) => true;
|
||||||
|
|
||||||
|
await cliente.ConnectAsync(servidorSMTP, puerto, SecureSocketOptions.StartTls);
|
||||||
|
await cliente.AuthenticateAsync(new SaslMechanismOAuth2(config.Remitente, tokenOAuth));
|
||||||
|
await cliente.SendAsync(mensaje);
|
||||||
|
await cliente.DisconnectAsync(true);
|
||||||
|
}
|
||||||
|
public static async Task EnviarCorreoMSAsync(GmailConfig config,
|
||||||
|
string tokenOAuth,
|
||||||
|
string destinatarios,
|
||||||
|
string asunto,
|
||||||
|
string cuerpo,
|
||||||
|
bool cuerpoHtml = false,
|
||||||
|
string cc = "",
|
||||||
|
string bcc = "",
|
||||||
|
string responderA = "",
|
||||||
|
MemoryStream[] FicherosAdjuntos = null,
|
||||||
|
String[] NombreFicherosAdjuntos = null,
|
||||||
|
string servidorSMTP = "smtp.gmail.com",
|
||||||
|
int puerto = 587)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(tokenOAuth))
|
||||||
|
tokenOAuth = await GmailTokenManager.ObtenerAccessTokenAsync(config);
|
||||||
|
|
||||||
|
var mensaje = new MimeMessage();
|
||||||
|
mensaje.From.Add(new MailboxAddress(config.NombreRemitente ?? config.Remitente, config.Remitente));
|
||||||
|
|
||||||
|
foreach (var d in destinatarios.Split(';').Where(x => !string.IsNullOrWhiteSpace(x)))
|
||||||
|
mensaje.To.Add(new MailboxAddress(d.Trim(), d.Trim()));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(cc))
|
||||||
|
foreach (var c in cc.Split(';'))
|
||||||
|
mensaje.Cc.Add(new MailboxAddress(c.Trim(), c.Trim()));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(bcc))
|
||||||
|
foreach (var b in bcc.Split(';'))
|
||||||
|
mensaje.Bcc.Add(new MailboxAddress(b.Trim(), b.Trim()));
|
||||||
|
|
||||||
|
mensaje.ReplyTo.Add(new MailboxAddress(
|
||||||
|
string.IsNullOrWhiteSpace(responderA) ? config.NombreRemitente : responderA,
|
||||||
|
string.IsNullOrWhiteSpace(responderA) ? config.Remitente : responderA));
|
||||||
|
|
||||||
|
mensaje.Subject = asunto.Replace("\r", "").Replace("\n", " ");
|
||||||
|
|
||||||
|
var builder = new BodyBuilder
|
||||||
|
{
|
||||||
|
HtmlBody = cuerpoHtml ? cuerpo : null,
|
||||||
|
TextBody = cuerpoHtml ? null : cuerpo
|
||||||
|
};
|
||||||
|
|
||||||
|
if (FicherosAdjuntos != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (int i = 0; i < NombreFicherosAdjuntos.Length; i++)
|
||||||
|
{
|
||||||
|
builder.Attachments.Add(NombreFicherosAdjuntos[i], FicherosAdjuntos[i].ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mensaje.Body = builder.ToMessageBody();
|
||||||
|
|
||||||
|
var cliente = new MailKit.Net.Smtp.SmtpClient();
|
||||||
|
cliente.ServerCertificateValidationCallback = (s, c, ch, e) => true;
|
||||||
|
|
||||||
|
await cliente.ConnectAsync(servidorSMTP, puerto, SecureSocketOptions.StartTls);
|
||||||
|
await cliente.AuthenticateAsync(new SaslMechanismOAuth2(config.Remitente, tokenOAuth));
|
||||||
|
await cliente.SendAsync(mensaje);
|
||||||
|
await cliente.DisconnectAsync(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
31
GmailTokenManager.cs
Normal file
31
GmailTokenManager.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using Google.Apis.Auth.OAuth2;
|
||||||
|
using Google.Apis.Util.Store;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public static class GmailTokenManager
|
||||||
|
{
|
||||||
|
public static async Task<string> ObtenerAccessTokenAsync(GmailConfig config)
|
||||||
|
{
|
||||||
|
//var stream = new FileStream(config.ClientSecretPath, FileMode.Open, FileAccess.Read);
|
||||||
|
var stream = new MemoryStream(config.ClientSecret);
|
||||||
|
|
||||||
|
//var credencial = await GoogleWebAuthorizationBroker.AuthorizeAsync(
|
||||||
|
// GoogleClientSecrets.FromStream(stream).Secrets,
|
||||||
|
// new[] { "https://www.googleapis.com/auth/gmail.send" },
|
||||||
|
// config.Usuario,
|
||||||
|
// CancellationToken.None,
|
||||||
|
// new FileDataStore(config.TokenFolder, true)
|
||||||
|
//);
|
||||||
|
var credencial = await GoogleWebAuthorizationBroker.AuthorizeAsync(
|
||||||
|
GoogleClientSecrets.FromStream(stream).Secrets,
|
||||||
|
new[] { "https://mail.google.com/" },
|
||||||
|
config.Usuario,
|
||||||
|
CancellationToken.None,
|
||||||
|
new FileDataStore(config.TokenFolder, true)
|
||||||
|
);
|
||||||
|
|
||||||
|
return await credencial.GetAccessTokenForRequestAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
8
Models/GmailConfig.cs
Normal file
8
Models/GmailConfig.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
public class GmailConfig
|
||||||
|
{
|
||||||
|
public byte[] ClientSecret { get; set; }
|
||||||
|
public string TokenFolder { get; set; }
|
||||||
|
public string Usuario { get; set; }
|
||||||
|
public string Remitente { get; set; }
|
||||||
|
public string NombreRemitente { get; set; }
|
||||||
|
}
|
||||||
13
tsGmail.csproj
Normal file
13
tsGmail.csproj
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Google.Apis.Auth" Version="1.71.0" />
|
||||||
|
<PackageReference Include="MailKit" Version="4.13.0" />
|
||||||
|
<PackageReference Include="MimeKit" Version="4.13.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
25
tsGmail.sln
Normal file
25
tsGmail.sln
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.14.36511.14 d17.14
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tsGmail", "tsGmail.csproj", "{3F5B6ED9-A9AE-420C-8C73-4D8719FEFE4C}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{3F5B6ED9-A9AE-420C-8C73-4D8719FEFE4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3F5B6ED9-A9AE-420C-8C73-4D8719FEFE4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3F5B6ED9-A9AE-420C-8C73-4D8719FEFE4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3F5B6ED9-A9AE-420C-8C73-4D8719FEFE4C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {9C91B698-4AAB-428A-89DE-8E5F6900956E}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
Reference in New Issue
Block a user