2019-06-23 03:35:23 -07:00
import {
BINARY_ENCODING ,
2021-02-15 22:23:37 -08:00
IExecuteFunctions
2019-06-23 03:35:23 -07:00
} from 'n8n-core' ;
import {
2019-10-25 12:38:54 -07:00
IDataObject ,
2019-06-23 03:35:23 -07:00
INodeExecutionData ,
INodeType ,
2020-10-01 05:01:39 -07:00
INodeTypeDescription ,
2021-04-16 09:33:36 -07:00
NodeOperationError ,
2019-06-23 03:35:23 -07:00
} from 'n8n-workflow' ;
import { createTransport } from 'nodemailer' ;
2019-10-25 12:38:54 -07:00
import SMTPTransport = require ( 'nodemailer/lib/smtp-transport' ) ;
2019-06-23 03:35:23 -07:00
export class EmailSend implements INodeType {
description : INodeTypeDescription = {
displayName : 'Send Email' ,
name : 'emailSend' ,
icon : 'fa:envelope' ,
group : [ 'output' ] ,
version : 1 ,
description : 'Sends an Email' ,
defaults : {
name : 'Send Email' ,
2019-07-26 02:41:08 -07:00
color : '#00bb88' ,
2019-06-23 03:35:23 -07:00
} ,
inputs : [ 'main' ] ,
outputs : [ 'main' ] ,
credentials : [
{
name : 'smtp' ,
required : true ,
2020-10-22 06:46:03 -07:00
} ,
2019-06-23 03:35:23 -07:00
] ,
properties : [
2020-02-24 08:21:03 -08:00
// TODO: Add choice for text as text or html (maybe also from name)
2019-06-23 03:35:23 -07:00
{
displayName : 'From Email' ,
name : 'fromEmail' ,
type : 'string' ,
default : '' ,
required : true ,
placeholder : 'admin@example.com' ,
description : 'Email address of the sender optional with name.' ,
} ,
{
displayName : 'To Email' ,
name : 'toEmail' ,
type : 'string' ,
default : '' ,
required : true ,
placeholder : 'info@example.com' ,
description : 'Email address of the recipient.' ,
} ,
2019-10-08 05:40:47 -07:00
{
displayName : 'CC Email' ,
name : 'ccEmail' ,
type : 'string' ,
default : '' ,
placeholder : 'cc@example.com' ,
description : 'Email address of CC recipient.' ,
} ,
2020-02-24 08:21:03 -08:00
{
displayName : 'BCC Email' ,
name : 'bccEmail' ,
type : 'string' ,
default : '' ,
placeholder : 'bcc@example.com' ,
description : 'Email address of BCC recipient.' ,
} ,
2019-06-23 03:35:23 -07:00
{
displayName : 'Subject' ,
name : 'subject' ,
type : 'string' ,
default : '' ,
placeholder : 'My subject line' ,
description : 'Subject line of the email.' ,
} ,
{
displayName : 'Text' ,
name : 'text' ,
type : 'string' ,
typeOptions : {
alwaysOpenEditWindow : true ,
rows : 5 ,
} ,
default : '' ,
description : 'Plain text message of email.' ,
} ,
{
displayName : 'HTML' ,
name : 'html' ,
type : 'string' ,
typeOptions : {
rows : 5 ,
} ,
default : '' ,
description : 'HTML text message of email.' ,
} ,
{
displayName : 'Attachments' ,
name : 'attachments' ,
type : 'string' ,
default : '' ,
description : 'Name of the binary properties which contain<br />data which should be added to email as attachment.<br />Multiple ones can be comma separated.' ,
} ,
2019-10-25 12:38:54 -07:00
{
displayName : 'Options' ,
name : 'options' ,
type : 'collection' ,
placeholder : 'Add Option' ,
default : { } ,
options : [
{
displayName : 'Ignore SSL Issues' ,
name : 'allowUnauthorizedCerts' ,
type : 'boolean' ,
default : false ,
description : 'Do connect even if SSL certificate validation is not possible.' ,
} ,
] ,
} ,
2019-06-23 03:35:23 -07:00
] ,
} ;
2021-03-29 02:20:10 -07:00
async execute ( this : IExecuteFunctions ) : Promise < INodeExecutionData [ ] [ ] > {
2021-02-15 22:23:37 -08:00
const items = this . getInputData ( ) ;
2019-06-23 03:35:23 -07:00
2021-02-15 22:23:37 -08:00
const returnData : INodeExecutionData [ ] = [ ] ;
const length = items . length as unknown as number ;
let item : INodeExecutionData ;
2019-06-23 03:35:23 -07:00
2021-02-15 22:23:37 -08:00
for ( let itemIndex = 0 ; itemIndex < length ; itemIndex ++ ) {
2021-07-19 23:58:54 -07:00
try {
2021-03-29 02:20:10 -07:00
2021-07-19 23:58:54 -07:00
item = items [ itemIndex ] ;
2021-02-15 23:09:10 -08:00
2021-07-19 23:58:54 -07:00
const fromEmail = this . getNodeParameter ( 'fromEmail' , itemIndex ) as string ;
const toEmail = this . getNodeParameter ( 'toEmail' , itemIndex ) as string ;
const ccEmail = this . getNodeParameter ( 'ccEmail' , itemIndex ) as string ;
const bccEmail = this . getNodeParameter ( 'bccEmail' , itemIndex ) as string ;
const subject = this . getNodeParameter ( 'subject' , itemIndex ) as string ;
const text = this . getNodeParameter ( 'text' , itemIndex ) as string ;
const html = this . getNodeParameter ( 'html' , itemIndex ) as string ;
const attachmentPropertyString = this . getNodeParameter ( 'attachments' , itemIndex ) as string ;
const options = this . getNodeParameter ( 'options' , itemIndex , { } ) as IDataObject ;
2019-06-23 03:35:23 -07:00
2021-08-20 09:57:30 -07:00
const credentials = await this . getCredentials ( 'smtp' ) ;
2019-06-23 03:35:23 -07:00
2021-07-19 23:58:54 -07:00
if ( credentials === undefined ) {
throw new NodeOperationError ( this . getNode ( ) , 'No credentials got returned!' ) ;
}
2019-10-25 12:38:54 -07:00
2021-07-19 23:58:54 -07:00
const connectionOptions : SMTPTransport.Options = {
host : credentials.host as string ,
port : credentials.port as number ,
secure : credentials.secure as boolean ,
2021-02-15 22:23:37 -08:00
} ;
2019-06-23 03:35:23 -07:00
2021-07-19 23:58:54 -07:00
if ( credentials . user || credentials . password ) {
// @ts-ignore
connectionOptions . auth = {
user : credentials.user as string ,
pass : credentials.password as string ,
} ;
}
if ( options . allowUnauthorizedCerts === true ) {
connectionOptions . tls = {
rejectUnauthorized : false ,
} ;
}
const transporter = createTransport ( connectionOptions ) ;
// setup email data with unicode symbols
const mailOptions = {
from : fromEmail ,
to : toEmail ,
cc : ccEmail ,
bcc : bccEmail ,
subject ,
text ,
html ,
2021-02-15 22:23:37 -08:00
} ;
2019-06-23 03:35:23 -07:00
2021-07-19 23:58:54 -07:00
if ( attachmentPropertyString && item . binary ) {
const attachments = [ ] ;
const attachmentProperties : string [ ] = attachmentPropertyString . split ( ',' ) . map ( ( propertyName ) = > {
return propertyName . trim ( ) ;
2021-02-15 22:23:37 -08:00
} ) ;
2019-06-23 03:35:23 -07:00
2021-07-19 23:58:54 -07:00
for ( const propertyName of attachmentProperties ) {
if ( ! item . binary . hasOwnProperty ( propertyName ) ) {
continue ;
}
attachments . push ( {
filename : item.binary [ propertyName ] . fileName || 'unknown' ,
content : Buffer.from ( item . binary [ propertyName ] . data , BINARY_ENCODING ) ,
} ) ;
}
if ( attachments . length ) {
// @ts-ignore
mailOptions . attachments = attachments ;
}
2021-02-15 22:23:37 -08:00
}
2021-07-19 23:58:54 -07:00
// Send the email
const info = await transporter . sendMail ( mailOptions ) ;
returnData . push ( { json : info as unknown as IDataObject } ) ;
2021-03-29 02:20:10 -07:00
2021-07-19 23:58:54 -07:00
} catch ( error ) {
if ( this . continueOnFail ( ) ) {
returnData . push ( { json : { error : error.message } } ) ;
continue ;
}
throw error ;
}
2021-02-15 22:23:37 -08:00
}
2021-03-29 02:20:10 -07:00
2021-02-15 22:23:37 -08:00
return this . prepareOutputData ( returnData ) ;
2019-06-23 03:35:23 -07:00
}
}