Why am I getting a MessageRejected error? - amazon-ses

I have a lambda to send emails using the aws sdkv3 for javascript. I am sending to verified email address. The exception returned does not tell me what the root causes might be as it is not one of their common errors.
Please look at my code and tell me if anyone sees and error in them template or the code.
exports.sendTestEmail = async (address, task_id) => {
console.log(`send email to ${address}`);
const tmpltChngParams = {
Destination: { /* required */
CcAddresses: [],
ToAddresses: [address]
},
Message: {
Body: {
Html: {
Data: '<p> There was a change made that has impacted Requirements Submission.'
+ 'A task has been created to track this process.</p>',
Charset: 'utf-8'
},
Text: {
Data: 'There was a change made that has impacted Requirements Submission. '
+ 'A task has been created to track this process.',
Charset: 'utf-8'
}
},
Subject: {
Data: ` System Notification: Task ${task_id}, `,
Charset: 'utf-8'
}
},
Source: 'aws-notifications-acct_num#someplace.com', /* required */
ReplyToAddresses: [],
};
const sesclient = new SES({ region: 'us-east-1' });
const command = new SendEmailCommand(tmpltChngParams);
try {
const sendPromise = await sesclient.send(command);
console.log(`Message ID = ${sendPromise.MessageId}`);
return sendPromise;
} catch (err) {
console.error(err, err.stack);
return err;
}
};
When trying to send I get the following exception in the logs:
2021-08-11T13:26:18.210Z e40afcd0-99f1-47ad-90bc-1c7d95f82699 ERROR MessageRejected: MessageRejected
at deserializeAws_querySendEmailCommandError (/var/task/node_modules/#aws-sdk/client-ses/dist/cjs/protocols/Aws_query.js:3368:41)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async /var/task/node_modules/#aws-sdk/middleware-serde/dist/cjs/deserializerMiddleware.js:6:20
at async /var/task/node_modules/#aws-sdk/middleware-signing/dist/cjs/middleware.js:12:24
at async StandardRetryStrategy.retry (/var/task/node_modules/#aws-sdk/middleware-retry/dist/cjs/defaultStrategy.js:56:46)
at async /var/task/node_modules/#aws-sdk/middleware-logger/dist/cjs/loggerMiddleware.js:6:22
at async Object.exports.sendTestEmail (/var/task/emailTest.js:34:25)
at async /var/task/routes/countryOwnersRoutes.js:77:16
at async /var/task/node_modules/lambda-api/index.js:231:23 {
'$fault': 'client',
'$metadata': {
httpStatusCode: 400,
requestId: '3f5f10fe-2c95-43e1-a720-a859bd7abc84',
extendedRequestId: undefined,
cfId: undefined,
attempts: 1,
totalRetryDelay: 0
}
} MessageRejected: MessageRejected
at deserializeAws_querySendEmailCommandError (/var/task/node_modules/#aws-sdk/client-ses/dist/cjs/protocols/Aws_query.js:3368:41)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
at async /var/task/node_modules/#aws-sdk/middleware-serde/dist/cjs/deserializerMiddleware.js:6:20
at async /var/task/node_modules/#aws-sdk/middleware-signing/dist/cjs/middleware.js:12:24
at async StandardRetryStrategy.retry (/var/task/node_modules/#aws-sdk/middleware-retry/dist/cjs/defaultStrategy.js:56:46)
at async /var/task/node_modules/#aws-sdk/middleware-logger/dist/cjs/loggerMiddleware.js:6:22
at async Object.exports.sendTestEmail (/var/task/emailTest.js:34:25)
at async /var/task/routes/countryOwnersRoutes.js:77:16
at async /var/task/node_modules/lambda-api/index.js:231:23

Related

AWS SDK for JavaScript v3 PutObjectCommand error 'A header you provided implies functionality that is not implemented'

I'm trying to upload a file with node.js from my client app (electron) to an S3 bucket in this manner:
const { S3Client, PutObjectCommand } = require('#aws-sdk/client-s3');
const s3Client = new S3Client({
region: 'eu-central-1',
credentials: {
accessKeyId: 'access',
secretAccessKey: 'secret',
},
});
const uploadFileToS3 = async (f) => {
const bucketParams = {
ACL: 'private',
Bucket: 'bucket',
Key: f.name,
Body: f.data,
ServerSideEncryption: 'AES256',
ContentType: 'image/png',
};
try {
return await s3Client
.send(new PutObjectCommand(bucketParams))
.then((result) => {
return process.send({
type: 'success',
fileName: f.name,
result,
});
});
} catch (erro) {
process.send({
type: 'error',
fileName: f.name,
error: erro,
});
}
};
process.on('message', (file) => {
uploadFileToS3(file);
});
I get the following error, that I'm unable to understand:
error: {
name: 'NotImplemented',
'$fault': 'client',
'$metadata': {
httpStatusCode: 501,
requestId: 'PXEBV6H4MX3',
extendedRequestId: 'yyyyyy',
attempts: 1,
totalRetryDelay: 0
},
Code: 'NotImplemented',
Header: 'Transfer-Encoding',
RequestId: 'PXEBV6H4MX3',
HostId: 'yyyyyy',
message: 'A header you provided implies functionality that is not implemented'
}
The file is a buffer generated with:
fs.readFileSync(pth)
Any idea of what could caused this error ?
Seems like the buffer created with
fs.readFileSync(pth)
was rejected and I could only use a stream:
const readableStream = await createReadStream(Buffer.from(f));
Maybe I'm wrong but it is possible that the actual SDK version is unable to accept a buffer yet, this could be the reason for that "missing functionality" message.

Express can't set headers after they are sent to the client

I have the following code:
router.post('/:email/addWorkflow', async function (req, res, next) {
const params = req.params;
const workflow = req.body;
const email = params.email;
User.findOne({ email: email }, function (err, user) {
if (err) {
res.status(500).send({
error: 'Error while querying database'
});
} else if (user) {
const workflows = user.workflows;
workflows.forEach(wf => {
if (wf) {
if (wf.workflowId === workflow.workflowId) {
res.status(409).send({
error: 'Workflow with that id already exists'
});
}
}
});
workflows.push(workflow);
User.updateOne({ email: email }, { $set: { workflows: workflows } }, { upsert: false }, function (err) {
if (err) {
res.status(500).send({
message: 'Error while updating database'
});
} else {
res.status(200).send({
message: 'Wf added successfully'
});
}
});
} else {
res.status(404).send({
message: 'No such user'
});
}
});
});
After I make a post with an already existing workflowId, I get the following error:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:485:11)
..........
at /home/petar/Documents/jsProjects/p/backend/routes/users.js:50:29
at CoreDocumentArray.forEach (<anonymous>)
at /home/petar/Documents/jsProjects/p/backend/routes/users.js:47:17
at /home/petar/Documents/jsProjects/p/backend/node_modules/mongoose/lib/model.js:4915:16
at /home/petar/Documents/jsProjects/p/backend/node_modules/mongoose/lib/model.js:4915:16
at /home/petar/Documents/jsProjects/linear-mixed-models/backend/node_modules/mongoose/lib/query.js:4380:11
[... lines matching original stack trace ...]
at processTicksAndRejections (internal/process/task_queues.js:76:11) {
code: 'ERR_HTTP_HEADERS_SENT'
Any ideas? I looked at other posts for the same error. I understand that it happens if I try to send response 2 time: res.send({...}) and res.send({...}). However, this does not happen in my case. Thanks in advance
I am not completely sure what line the error message is indicating, but the following loop is the only place I can think of a multiple response on your code
workflows.forEach(wf => {
//foreach is looping
if (wf) {
if (wf.workflowId === workflow.workflowId) {
res.status(409).send({
error: 'Workflow with that id already exists'
});
//but I don't think this guy will stop looping after the first "send()"
}
}
});

Catch error server response with #nuxtjs/auth

I'm trying to catch the error response for #nuxtjs/auth but it doesn't seem to return anything but undefined.
It refuses to login if I include the user so I want to know why it's returning undefined.
CONFIG:
auth: {
strategies: {
local: {
endpoints: {
login: {
url: 'http://127.0.0.1:80/api/login',
method: 'post',
propertyName: 'token'
},
logout: false,
user: {
url: 'http://127.0.0.1:80/api/me',
method: 'get',
propertyName: undefined
}
},
tokenRequired: true,
tokenType: 'bearer',
}
},
plugins: [
'#/plugins/auth.js'
]
},
PLUGIN:
export default function ({ app }) {
app.$auth.onError((error, name, endpoint) => {
console.error(name, error)
});
}
VIEW FUNCTION:
- both handleSuccess and handleFailure returns undefined.
login() {
this.toggleProcessing(0);
let payload = {
username: 'admin',
password: 'admin123'
}
let handleSuccess = response => {
console.log(response);
this.toggleProcessing(0);
}
let handleFailure = error => {
console.log(error);
this.toggleProcessing(0);
}
this.$auth.loginWith('local', { data: payload }).then(handleSuccess).catch(handleFailure);
},
You can use e.response
async login() {
try {
const login = {
username: this.username,
password: this.password
}
let response = await this.$auth.loginWith('local', { data: login })
console.log('response', response)
} catch (e) {
console.log('Error Response', e.response)
}
}
I fell into the same problem and after spending some time i found out a very good way to catch the response. The solution is to use the axios interceptor. Just replace your plugin file code with the following
export default function ({$axios, $auth}){
$axios.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
}
I'm not sure initially what might be wrong here because I can't see the complete nuxt.config.js and your full component but here are a few things to check:
#nuxtjs/axios is installed
Both axios and auth modules are registered in the modules section of nuxt.config.js:
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth'
]
Also, ensure the middleware property for auth is set in the component/page component.
Ensure you're following the documentation on this page: https://auth.nuxtjs.org/getting-starterd/setup
Ive been using try -> this.$auth.loginWith to catch error server response with #nuxtjs/auth.
login() {
const data = { form };
try {
this.$auth
.loginWith("local", { data: data })
.then(api => {
// response
this.response.success = "Succes";
})
.catch(errors => {
this.response.error = "Wrong username/password";
});
} catch (e) {
this.response.error = e.message;
}
},
Specify the token field in the nuxt.config
strategies: {
local: {
endpoints: {
login: { // loginWith
url: "auth/login",
method: "post",
propertyName: "data.token" // token field
},
user: { // get user data
url: "auth/user",
method: "get",
propertyName: "data.user"
},
}
}
},
modules: ["#nuxtjs/axios", "#nuxtjs/auth"],

Unhandled promise rejection: Error: Request failed with status code 500

I am trying to call an api and I get the error "Unhandled promise rejection: Error: Request failed with status code 500". I dunno how did I get the error.I put the api call in componentDidMount. I am not sure whether the error comes from the redux implementation or from how I called the api.
This is how I called the api. After a successful login, I put the username as a token and use it to call another api.
state={
username: '',
semcode: [
{}
]
}
componentWillMount() {
AsyncStorage.getItem('Login_token').then((token) => {
console.log('this is coursescreen',token);
let Login_token = token;
this.setState({ username: Login_token });
});
}
componentDidMount(){
this.props.getSemcode(this.state.username);
}
componentWillReceiveProps(nextProps) {
console.log('xx',nextProps);
if (nextProps.semCode != undefined) {
this.setState({ semcode: nextProps.semCode });
}
}
This is how I wrote my action file:
export const getSemcode = (username) => async dispatch => {
let param = {
nomatrik: username,
}
console.log(`${helper.ROOT_URL}/result/GetListOfKodSesiSem`)
let code_res = await
axios.post(`${helper.ROOT_URL}/result/GetListOfKodSesiSem`, param)
console.log(code_res.data);
if (code_res.data.length > 0) {
const { code } = code_res.data;
dispatch({ type: SEMCODE_FETCH_SUCCESS, payload: { semCode: code }});
}
}
This is how I wrote my reducer:
import { SEMCODE_FETCH_SUCCESS} from '../actions/types';
const INITIAL_STATE={
semCode:[],
}
export default function (state=INITIAL_STATE, action){
switch(action.type){
case SEMCODE_FETCH_SUCCESS:
return action.payload
default:
return state;
}
}
Can anyone help me pleaseeeeee
Error Message
Error received from axios.post: {"config":{"transformRequest":
{},"transformResponse":{},"timeout":0,"xsrfCookieName":"XSRF-
TOKEN","xsrfHeaderName":"X-XSRF-TOKEN","maxContentLength":-1,"headers":
{"Accept":"application/json, text/plain, /","Content-
Type":"application/json;charset=utf-8"},
"method":"post","nomatrik":"BB16160907",
"url":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem","data":"
{\"Accept\":\"application/json\",\"Content-
Type\":\"application/json\"}"},"request":
{"UNSENT":0,"OPENED":1,"HEADERS_RECEIVED":2,"LOADING":3,"DONE":4,
"readyState":4,"status":500,"timeout":0,"withCredentials":true,"upload":
{},"_aborted":false,"_hasError":false,"_method":"POST","_response":"
{\"Message\":\"An error has occurred.\"}",
"_url":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem",
"_timedOut":false,"_trackingName":"unknown",
"_incrementalEvents":false,"responseHeaders":{"Date":"Sat, 30 Dec 2017
03:58:25
GMT","Content-Length":"36","X-Powered-By":"ARR/3.0","X-AspNet-
Version":"4.0.30319","Expires":"-1","Content-Type":"application/json;
charset=utf-8","Server":"Microsoft-IIS/10.0","Pragma":"no-cache","Cache-
Control":"no-cache"},"_requestId":null,"_headers":
{"accept":"application/json, text/plain, /","content-
type":"application/json;charset=utf-
8"},"_responseType":"","_sent":true,"_lowerCaseResponseHeaders":{"date":"Sat,
30 Dec 2017 03:58:25
GMT","content-length":"36","x-powered-by":"ARR/3.0","x-
aspnet-version":"4.0.30319","expires":"-1","content-type":"application/json; charset=utf-8","server":"Microsoft-IIS/10.0","pragma":"no-cache","cache-
control":"no-cache"},"_subscriptions":[],"responseURL":
"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem"},"response":{"data":
{"Message":"An error has
occurred."},"status":500,"headers":{"date":"Sat, 30 Dec 2017 03:58:25
GMT","content-length":"36","x-powered-by":"ARR/3.0","x-
aspnet-version":"4.0.30319","expires":"-1","content-type":"application/json; charset=utf-8","server":"Microsoft-IIS/10.0","pragma":"no-cache","cache-
control":"no-cache"},"config":{"transformRequest":{},"transformResponse":
{},"timeout":0,"xsrfCookieName":"XSRF-TOKEN","xsrfHeaderName":"X-XSRF-
TOKEN","maxContentLength":-1,"headers":{"Accept":"application/json,
text/plain,
/","Content-Type":"application/json;charset=utf-8"},"method": "post","nomatrik":"BB16160907",
"url":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem","data":"
{\"Accept\":\"application/json\",\"Content-
Type\":\"application/json\"}"},"request":
{"UNSENT":0,"OPENED":1,"HEADERS_RECEIVED":2,"LOADING":3,"DONE":4,
"readyState":4,"status":500,"timeout":0,"withCredentials":true,"upload":
{},"_aborted":false,"_hasError":false,"_method":"POST","_response":"
{\"Message\":\"An error has occurred.\"}",
"_url":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem",
"_timedOut":false,"_trackingName":"unknown","_incrementalEvents":false, "responseHeaders":{"Date":"Sat, 30 Dec 2017 03:58:25 GMT","Content-
Length":"36","X-Powered-By":"ARR/3.0","X-AspNet-
Version":"4.0.30319","Expires":"-1","Content-Type":"application/json;
charset=utf-8","Server":"Microsoft-IIS/10.0","Pragma":"no-cache","Cache-
Control":"no-cache"},"_requestId":null,"_headers":
{"accept":"application/json, text/plain, /","content-
type":"application/json;charset=utf-
8"},"_responseType":"","_sent":true,"_lowerCaseResponseHeaders":{"date":"Sat,
30 Dec 2017 03:58:25
GMT","content-length":"36","x-powered-by":"ARR/3.0","x-
aspnet-version":"4.0.30319","expires":"-1","content-type":"application/json; charset=utf-8","server":"Microsoft-IIS/10.0","pragma":"no-cache","cache-
control":"no-cache"},"_subscriptions":
[],"responseURL":"https://smp.ums.edu.my/api/result/GetListOfKodSesiSem"}}}
Login action:
export const attemptLogin = (username, password) => async dispatch => {
let param = {
txtNomatrik: username,
txtPwd: password,
public_key: helper.PUBLIC_KEY,
secret_key: helper.SECRET_KEY
}
console.log(`${helper.ROOT_API_URL}/v1/basic/ad/std/login`)
let login_res = await
axios.post(`${helper.ROOT_API_URL}/v1/basic/ad/std/login`, param)
console.log(login_res.data);
await AsyncStorage.setItem('jwtToken',login_res.data.token);
if (login_res.data.status == 'Successful login') {
const { login } = login_res.data;
dispatch({ type: LOGIN_SUCCESS});
}
}
Problem
Your request is failing because you are not adding the JWT token to the headers.
Solution
Using Axios and with your code this should work. Evidently our big problem here was that you have to pass data even though it is empty. If we do not pass data it fails with error 500.
export const getSemcode = (username) => async dispatch => {
let jwtToken = await AsyncStorage.getItem('jwtToken').then((data) => {
console.log('this is semcode',data);
});
let config = {
method: 'POST',
url: 'url/to/sem',
headers: {
'content-type': 'application/x-www-form-urlencoded',
AntiTemperSignature: jwtToken,
UserID: '123456',
},
data: '',
json: true
};
try {
return axios(config)
.then((response) => {
console.log(response);
if (response.data.length > 0) {
const { code } = response.data;
dispatch({ type: SEMCODE_FETCH_SUCCESS, payload: { semCode: code } });
}
})
.catch((error) => {
console.log(error);
});
}
}
You are looking in the wrong place.
An error code 500 is returned by the remote server when it can't handle the request. In this case, I suspect that the POST to ${helper.ROOT_URL}/result/GetListOfKodSesiSem is failing. The axios library is a promise based library. Wrap the call in a try-catch block like this:
try {
console.log(`${helper.ROOT_URL}/result/GetListOfKodSesiSem`)
let code_res = await
axios.post(`${helper.ROOT_URL}/result/GetListOfKodSesiSem`, param)
console.log(code_res.data);
if (code_res.data.length > 0) {
const { code } = code_res.data;
dispatch({ type: SEMCODE_FETCH_SUCCESS, payload: { semCode: code }});
}
} catch (err) {
console.error(`Error received from axios.post: ${JSON.stringify(err)}`);
}
This will at least give you a view in your debug console on what is happening. You can then coordinate that call with any debug logs from the backend to figure out what the error really is.
Your root cause, however, is that the remote server is returning a Server Error (HTTP code 500) to your client.

No error shown in console when thrown from inside hapi plugin

For some reason no error shows up in the server console when I start my hapi server with nodemon and navigate to http://localhost:3000/hapi-ext-fetch and this makes debugging very difficult. Here is my code:
var Hapi = require('hapi');
var Joi = require('joi');
var fetch = require('isomorphic-fetch');
var debugMode = { debug: { request: [ 'error', 'request-internal' ] }};
var server = new Hapi.Server(debugMode);
server.connection({ port: 3000 });
var myPlugin = {
register: function (server, options, next) {
server.route([
{
method: 'GET',
path: '/{name}',
handler: function ( request, reply ) {
throw new Error('this error isnt shown!');
},
config: {
validate: {
params: {
name: Joi.string().min(3).max(10)
}
}
}
}
]);
next();
}
};
myPlugin.register.attributes = {
name: 'myPlugin',
version: '1.0.0'
};
server.register([
{
register: myPlugin,
routes: {
prefix: '/test'
}
}
], function() {
server.ext( 'onPreResponse', ( request, reply ) => {
if ( typeof request.response.statusCode !== 'undefined' ) {
return reply.continue();
}
fetch('http://localhost:3000/test/whatever')
.then(function(result) {
reply(result);
})
.catch(function(err) {
reply('error on server side: ' + err.stack);
});
});
server.start((err) => {
if (err) {
throw err;
}
console.log('Server running at:', server.info.uri);
});
});
I'm using hapi 13.0.0
Can't say I totally understand your use case here and if this question will be helpful to other people. But what you're trying to do it seems is:
Send a request to /hapi-fetch-ext
Have that request 404
And then in an onPreResponse go fetch another route /test/whatever
Hope to see the "this error isn't shown error"
Not sure if you're aware but this is going to cause an infinite cycle of requests (your fetch will cause another onPreResponse and so on and so on). So you should probably only go fetch on a 404:
server.ext( 'onPreResponse', ( request, reply ) => {
if (request.response.isBoom && request.response.output.statusCode === 404) {
return fetch('http://localhost:3000/test/whatever')
.then(function(result) {
reply(result);
})
.catch(function(err) {
reply('error on server side: ' + err.stack);
});
}
return reply.continue();
});