Agregar archivos de proyecto.

This commit is contained in:
2025-09-18 13:00:36 +02:00
parent f7e2037014
commit 0a4437ff99
7 changed files with 944 additions and 0 deletions

5
Documentos/Enlaces.txt Normal file
View 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

207
GmailOAuthSender.cs Normal file
View 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
View 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
View 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
View 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
View 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