Open mattr5341989 opened 1 year ago
What is you whole Error log?
First thing I would check if I were you is the forwardMapping object. You currently have:
forwardMapping: { "@protonmail.com" : [ "[forwardEmail@protonmail.com](mailto:forwardEmail@protonmail.com)"] }
Meaning you have a catch-all for [anything]@protonmail.com and then forwarding them to forwardEmail@protonmail.com, which sounds like a loop to me. But anyway, make sure you have that set correctly.
So check that out, and also make sure you have verified your domain name (e.g. protonmail.com in your example). Otherwise, you should use a verified emailed identity, if you can't verify your domain. If you don't know what I'm talking about, see here: https://docs.aws.amazon.com/ses/latest/dg/verify-addresses-and-domains.html
Hope that helps. If not, let us know.
I've seen 4 other issues like this but none of them seem to have an answer as to why.. or at least not in my situation. Here is my lambda function. Please help.
`"use strict"; var AWS = require('aws-sdk');
console.log("AWS Lambda SES Forwarder // @arithmetric // Version 5.0.0");
// Configure the S3 bucket and key prefix for stored raw emails, and the // mapping of email addresses to forward from and to. // // Expected keys/values: // // - fromEmail: Forwarded emails will come from this verified address // // - subjectPrefix: Forwarded emails subject will contain this prefix // // - emailBucket: S3 bucket name where SES stores emails. // // - emailKeyPrefix: S3 key name prefix where SES stores email. Include the // trailing slash. // // - allowPlusSign: Enables support for plus sign suffixes on email addresses. // If set to
true
, the username/mailbox part of an email address is parsed // to remove anything after a plus sign. For example, an email sent to //example+test@example.com
would be treated as if it was sent to //example@example.com
. // // - forwardMapping: Object where the key is the lowercase email address from // which to forward and the value is an array of email addresses to which to // send the message. // // To match all email addresses on a domain, use a key without the name part // of an email address before the "at" symbol (i.e.@example.com
). // // To match a mailbox name on all domains, use a key without the "at" symbol // and domain part of an email address (i.e.info
). // // To match all email addresses matching no other mapping, use "@" as a key. var defaultConfig = { fromEmail: "sales@inboundEmail.com", subjectPrefix: "", emailBucket: "cc-app-5058", emailKeyPrefix: "", allowPlusSign: true, forwardMapping: { "@protonmail.com" : [ "forwardEmail@protonmail.com"] } };/**
mail
andreceipients
data.@return {object} - Promise resolved with data. */ exports.parseEvent = function(data) { // Validate characteristics of a SES event record. if (!data.event || !data.event.hasOwnProperty('Records') || data.event.Records.length !== 1 || !data.event.Records[0].hasOwnProperty('eventSource') || data.event.Records[0].eventSource !== 'aws:ses' || data.event.Records[0].eventVersion !== '1.0') { data.log({ message: "parseEvent() received invalid SES message:", level: "error", event: JSON.stringify(data.event) }); return Promise.reject(new Error('Error: Received invalid SES message.')); }
data.email = data.event.Records[0].ses.mail; data.recipients = data.event.Records[0].ses.receipt.recipients; return Promise.resolve(data); };
/**
@return {object} - Promise resolved with data. / exports.transformRecipients = function(data) { var newRecipients = []; data.originalRecipients = data.recipients; data.recipients.forEach(function(origEmail) { var origEmailKey = origEmail.toLowerCase(); if (data.config.allowPlusSign) { origEmailKey = origEmailKey.replace(/+.?@/, '@'); } if (data.config.forwardMapping.hasOwnProperty(origEmailKey)) { newRecipients = newRecipients.concat( data.config.forwardMapping[origEmailKey]); data.originalRecipient = origEmail; } else { var origEmailDomain; var origEmailUser; var pos = origEmailKey.lastIndexOf("@"); if (pos === -1) { origEmailUser = origEmailKey; } else { origEmailDomain = origEmailKey.slice(pos); origEmailUser = origEmailKey.slice(0, pos); } if (origEmailDomain && data.config.forwardMapping.hasOwnProperty(origEmailDomain)) { newRecipients = newRecipients.concat( data.config.forwardMapping[origEmailDomain]); data.originalRecipient = origEmail; } else if (origEmailUser && data.config.forwardMapping.hasOwnProperty(origEmailUser)) { newRecipients = newRecipients.concat( data.config.forwardMapping[origEmailUser]); data.originalRecipient = origEmail;
} else if (data.config.forwardMapping.hasOwnProperty("@")) { newRecipients = newRecipients.concat( data.config.forwardMapping["@"]); data.originalRecipient = origEmail; } } });
if (!newRecipients.length) { data.log({ message: "Finishing process. No new recipients found for " + "original destinations: " + data.originalRecipients.join(", "), level: "info" }); return data.callback(); } data.recipients = newRecipients;
return Promise.resolve(data); };
/**
@return {object} - Promise resolved with data. */ exports.fetchMessage = function(data) { // Copying email object to ensure read permission data.log({ level: "info", message: "Fetching email at s3://" + data.config.emailBucket + '/' + data.config.emailKeyPrefix + data.email.messageId }); return new Promise(function(resolve, reject) { data.s3.copyObject({ Bucket: data.config.emailBucket, CopySource: data.config.emailBucket + '/' + data.config.emailKeyPrefix + data.email.messageId, Key: data.config.emailKeyPrefix + data.email.messageId, ACL: 'private', ContentType: 'text/plain', StorageClass: 'STANDARD' }, function(err) { if (err) { data.log({ level: "error", message: "copyObject() returned error:", error: err, stack: err.stack }); return reject( new Error("Error: Could not make readable copy of email.")); }
// Load the raw email from S3 data.s3.getObject({ Bucket: data.config.emailBucket, Key: data.config.emailKeyPrefix + data.email.messageId }, function(err, result) { if (err) { data.log({ level: "error", message: "getObject() returned error:", error: err, stack: err.stack }); return reject( new Error("Error: Failed to load message body from S3.")); } data.emailData = result.Body.toString(); return resolve(data); }); }); }); };
/**
@return {object} - Promise resolved with data. / exports.processMessage = function(data) { var match = data.emailData.match(/^((?:.+\r?\n))(\r?\n(?:.\s+))/m); var header = match && match[1] ? match[1] : data.emailData; var body = match && match[2] ? match[2] : '';
// Add "Reply-To:" with the "From" address if it doesn't already exists if (!/^reply-to:[\t ]?/mi.test(header)) { match = header.match(/^from:[\t ]?(.(?:\r?\n\s+.)*\r?\n)/mi); var from = match && match[1] ? match[1] : ''; if (from) { header = header + 'Reply-To: ' + from; data.log({ level: "info", message: "Added Reply-To address of: " + from }); } else { data.log({ level: "info", message: "Reply-To address not added because From address was not " + "properly extracted." }); } }
// SES does not allow sending messages from an unverified address, // so replace the message's "From:" header with the original // recipient (which is a verified domain) header = header.replace( /^from:[\t ]?(.(?:\r?\n\s+.))/mgi, function(match, from) { var fromText; if (data.config.fromEmail) { fromText = 'From: ' + from.replace(/<(.)>/, '').trim() + ' <' + data.config.fromEmail + '>'; } else { fromText = 'From: ' + from.replace('<', 'at ').replace('>', '') + ' <' + data.originalRecipient + '>'; } return fromText; });
// Add a prefix to the Subject if (data.config.subjectPrefix) { header = header.replace( /^subject:[\t ]?(.*)/mgi, function(match, subject) { return 'Subject: ' + data.config.subjectPrefix + subject; }); }
// Replace original 'To' header with a manually defined one if (data.config.toEmail) { header = header.replace(/^to:[\t ]?(.*)/mgi, () => 'To: ' + data.config.toEmail); }
// Remove the Return-Path header. header = header.replace(/^return-path:[\t ]?(.*)\r?\n/mgi, '');
// Remove Sender header. header = header.replace(/^sender:[\t ]?(.*)\r?\n/mgi, '');
// Remove Message-ID header. header = header.replace(/^message-id:[\t ]?(.*)\r?\n/mgi, '');
// Remove all DKIM-Signature headers to prevent triggering an // "InvalidParameterValue: Duplicate header 'DKIM-Signature'" error. // These signatures will likely be invalid anyways, since the From // header was modified. header = header.replace(/^dkim-signature:[\t ]?.\r?\n(\s+.\r?\n)*/mgi, '');
data.emailData = header + body; return Promise.resolve(data); };
/**
/**
Promise.series = function(promises, initValue) { return promises.reduce(function(chain, promise) { if (typeof promise !== 'function') { return Promise.reject(new Error("Error: Invalid promise item: " + promise)); } return chain.then(promise); }, Promise.resolve(initValue)); }; `