javascript - Enviar correo electrónico a través de una aplicación escrita en Electron/React/TS
Estoy intentando implementar un mecanismo de envío de correos electrónicos/Gmail en mi aplicación. Esta es una aplicación de escritorio con el contenido alojado escrito con la ayuda de React y Electron. He estado intentando implementarlo de varias maneras descritas en la web, usando varios módulos, googleapi, etc., pero siempre terminaba con algún error extraño y una descripción de problema aún más enigmática: el código generalmente se basaba en la sección de "Node.js" del artículo. No sé si entiendo completamente el lado de la arquitectura de este problema y si siquiera es posible activar el mecanismo de envío, o si es algo que debe implementarse en forma de un servicio del lado del servidor. Si alguien pudiera arrojar algo de luz sobre el problema, lo agradecería enormemente ya que ya he pasado demasiadas horas en el asunto. ¡Gracias de antemano!
Respuesta #1
¡Lo resolví (por fin!). Lo estoy escribiendo aquí con la esperanza de que ayude a alguien en el futuro.
La razón principal por la que todos los intentos y métodos fallaron conmigo fue que los estaba implementando en el proceso de renderizado/navegador en lugar del proceso principal de Electron/Node (según la documentación de Electron). Cuando trasladé la implementación descrita en detalle en este artículo (enfoque que utiliza nodemailer) al proceso principal, que en mi caso consistía prácticamente solo en electron.js, y la activé mediante ipc (comunicación entre procesos) desde el proceso de renderizado, ¡milagrosamente empezó a funcionar!
Gracias Robert por señalar este problema, ya que la siguiente declaración me puso en el camino correcto.
Estaba enfrentando el mismo problema al intentar implementar el código de nodemailer del lado del cliente. La razón era que nodemailer parece no funcionar en el navegador (solo en node). Moverlo al lado del servidor (a una aplicación express) resolvió el problema.
// electron.js
var nodemailer = require("nodemailer");
function SendIt() {
var transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: "[email ",
pass: "your_password",
},
});
const mailOptions = {
from: "[email ",
to: "[email ",
subject: "Subject of your email",
html: "<p>Your html here</p>",
};
transporter.sendMail(mailOptions, function (err, info) {
if (err) console.log(err);
else console.log(info);
});
}
electron.ipcMain.on("SendIt", (event, args) => {
console.log("ipcMain: Executing SendIt");
SendIt();
});
Respuesta #2
Si alguien está usando Quasar/Electron y quiere usar nodemailer. Esto me funciona. Estoy respondiendo a este mensaje porque es relevante para electron. Como indicó el autor original, nodemailer debe ejecutarse como un proceso de node y no puede ejecutarse en el proceso del renderer.
Puse el código de nodemailer dentro del archivo electron-preload.js (bajo el directorio src-electron).
Electron utiliza el Aislamiento de Contexto. Por lo tanto, el código de nodemailer necesita colocarse en el archivo electron-preload.js. Simplemente ponerlo en cualquier archivo .vue causará un error. El error que estaba obteniendo era: nodemailer.createTransport no es una función
Para superar el Aislamiento de Contexto, tuve que usar el Puente de Contexto como se explica en esta documentación de Electron: https://www.electronjs.org/docs/latest/tutorial/context-isolation
Para fines de prueba, estoy usando ethereal.email como se sugiere en la documentación de nodemailer.
electron-preload.js:
import { contextBridge } from 'electron'
contextBridge.exposeInMainWorld('myAPI', {
doAThing: (emailFrom, emailTo, emailSubject, emailHTML) => {
var nodemailer = require("nodemailer")
let transporter = nodemailer.createTransport({
host: "smtp.ethereal.email",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: '[email ',
pass: 'password'
},
})
const mailOptions = {
from: emailFrom,
to: emailTo,
subject: emailSubject,
html: emailHTML,
}
transporter.sendMail(mailOptions, function (err, info) {
if (err) console.log(err);
else console.log(info);
})
console.log("in the PreLoad Script")
}
}) // end contextBridge.exposeInMainWorld
Luego, en mi archivo .vue (estoy llamando al mío personDetails.vue), tengo un botón, y cuando se hace clic en él, dispara este método:
async sendEmailMethodSMTP() {
myAPI.doAThing(this.emailFrom, this.emailTo, this.emailSubject, this.emailHTML )
}, // end sendEmailMethodSMTP
Estoy recopilando la información de las variables en la información que estoy pasando desde el archivo .vue (this.emailFrom, this.emailTo, this.emailSubject, this.emailHTML), al método doAThing en el archivo electron-proload.js.
Cuando se presiona el botón, la información se envía al cargador previo, se activa nodemailer y se envía el correo electrónico.
No he compilado mi aplicación Quasar/Electron para asegurarme de que esto funcione en un entorno en vivo, pero al ejecutar Quasar en modo de desarrollo esto funciona muy bien.
