SendGrid - Not getting custom_args returned on bounce events - sendgrid-api-v3

When sending emails through SendGrid's Node mail client ("#sendgrid/mail": "^6.4.0") we are adding some custom_args to the JSON submitted and all of them are text values. The webhooks for processed, delivered, open, and click events return the custom_args to us as expected. But when we receive a webhook for the bounce event the custom_args are not attached.
We are submitting:
{ personalizations: [
{ to: {
email: 'recipient#example.com',
name: 'Recipient Name'
}
}
],
from:
{
email: 'sender#example.com',
name: 'Sender Name'
},
reply: {
email: 'replyto#example.com',
name: 'Reply To Name'
},
custom_args:
{ envelopeId: '4aa4f5f8-9ba4-4ec3-a6cf-3098107f498d',
messageId: '105',
eventId: '251' },
subject: 'Test Email 1234',
content:
[ { type: 'text/plain',
value:
'This is a sample email, please click here: https://example.com' },
{ type: 'text/html',
value:
'This is a sample email, please <a href=\'https://example.com\'>click here</a>' } ],
mail_settings: { sandbox_mode: { enable: false } } }```

Got an answer back from SendGrid on this one. The issue is when a mail server does a slow bounce where it takes them some time to sort out that they do not have anyone with that name locally, then they sometimes return a brand new email to the sending server and that causes SendGrid to loose all of the context that was placed in the initial email.

Related

AWS Cognito "invalid_state" error with federated identities

I'm using AWS cognito as a federated identity service to federate Salesforce IDP (we'll have more in the future)
Recently I started getting an "invalid state" error. And after days of research, I found out that:
when the authentication flow starts on cognito there is no error
cognito redirects the user to salesforce
user gets sent back to cognito after login
when the authentication flow starts on salesforce we receive the "invalid_state" error.
user logs in directly over salesforce
salesforce redirects the user to cognito
I need to be able to start the flow from salesforce for the following cases:
the first time user is registered in salesforce
when user reset's password in salesforce
The setup of AWS Cognito via CDK:
const userPool = new UserPool(this, 'duck-user-pool', {
autoVerify: {
email: true,
phone: false,
},
mfa: Mfa.OFF,
mfaSecondFactor: {
sms: false,
otp: false,
},
selfSignUpEnabled: false,
standardAttributes: {
email: {
mutable: true,
required: true,
},
}
});
const salesforceIdP = new CfnUserPoolIdentityProvider(
this,
'salesforceIdP',
{
attributeMapping: {
email: 'email',
family_name: 'family_name',
given_name: 'given_name',
},
providerDetails: {
attributes_request_method: 'GET',
authorize_scopes: 'email openid profile',
oidc_issuer: config.SalesforceBaseUrl,
client_id:
salesforceIdPCredentials.secretValueFromJson(
'CLIENT_ID'
),
client_secret:
salesforceIdPCredentials.secretValueFromJson(
'CLIENT_SECRET'
),
},
providerName: 'salesforce-idp',
providerType: 'OIDC',
userPoolId: userPool.userPoolId,
}
);
const spaClient = userPool.addClient(
'duck-user-pool-client-spa',
{
authFlows: {
userPassword: true,
userSrp: true,
},
generateSecret: false,
refreshTokenValidity: Duration.days(30),
supportedIdentityProviders: [
UserPoolClientIdentityProvider.COGNITO,
UserPoolClientIdentityProvider.custom(
salesforceIdP.providerName
),
],
oAuth: {
callbackUrls: config.CallbackURLs,
flows: {
authorizationCodeGrant: true,
implicitCodeGrant: false,
clientCredentials: false,
},
logoutUrls: config.LogoutURLs,
scopes: [
OAuthScope.EMAIL,
OAuthScope.OPENID,
OAuthScope.PHONE,
OAuthScope.PROFILE,
],
},
}
);
On the salesforce side, configuration was made to redirect the user to following url:
https://sandbox-duck.auth.eu-west-1.amazoncognito.com/oauth2/idpresponse
I've found out cognito is using a query parameter called state (against CSRF attacks) and if the parameter is not in the URL it throws this error.
The setup was working until a month ago but suddenly it stopped working. Is there a way to work around this limitation?

Storing messages in new conversation collections; MongoDB

I'm a student working on a chat application for my internship, where I use socket.io.
Right now I am busy thinking of a good way to store the messages send in conversations.
As of now I do the following:
For each conversation between one user and another user, a new collection is made.
On every message sent, the message is stored in the according conversation collection in a single document.
The collections:
Where the document looks as follows:
Now I wonder if there is a good argument to be made to have just one collection "conversations", and store all the messages in multiple documents, where each conversation is a new document.
Creating a new collection for every message is very bad idea instead of that you use a simple schema as given below to store your messages
const conversation_schema = new Schema({
from: {
type: ObjectID,
ref: 'User'
},
to: {
type: ObjectID,
ref: 'User'
},
messageBody: { // body of the message(text body/ image blob/ video blob)
type: String,
},
messageType: { // type of the message(text, mp3, mp4, etc...)
type: String,
},
read: { // to boolean flag to mark whether the to user has read the message
type: Boolean,
default: false,
},
createdAt: { // when was this message goit created
type: Date,
default: new Date(),
},
});
you can fetch the conversation between the two users using the following query
conversations.find({
$or: [
{from: 'user1', TO: 'user2},
{from: 'user2', TO: 'user1},
],
}).populate({ path: 'to', model: User })
.populate({ path: 'from', model: User })
.sort({ createdAt: -1 })

Use an array as response model in AWS Gateway cdk

I'm trying to create a typescript aws cdk to build up an API Gateway with this own swagger documentation.
There is one simple endpoint returning a list of "Supplier", but we don't know how to specify this in the cdk.
Here the code:
export function CreateSupplierMethods(apigw: apigateway.Resource,restApiId: string, scope: cdk.Construct, api: apigateway.RestApi) {
let suppliers = apigw.addResource('suppliers')
let supplierModel = new apigateway.Model(scope, "supplier-model", {
modelName: "supplier",
restApi: api,
contentType: 'application/json',
schema: {
description: "Supplier data",
title: "Supplier",
properties: {
code: { type: apigateway.JsonSchemaType.STRING, minLength: 4, maxLength: 6},
name: { type: apigateway.JsonSchemaType.STRING, maxLength: 81},
}
},
})
let getSuppliers = suppliers.addMethod('GET', new apigateway.MockIntegration(), {
methodResponses: [{
statusCode: "200",
responseModels: {
"application/json": supplierModel,
}
},
{
statusCode: "401",
}]
})
}
As you can see, the GET has the supplierModel as output.
How can I say "returns a list of supplierModel"? I wish I can use this model for both list of supplier and single instances of supplier (like a GET method with id as input).
Is this possible? If yes, how?
Looking the generated json, I'm trying to have something like this:
But what I'm getting now is quite different:
How can I get a result like the first image?
You are creating a model and assigning it to the method.
Create an array of those models and then assign that array to the method.
let supplierModelArray = new apigateway.Model(scope, "supplier-model-array", {
modelName: "supplier-array",
restApi: api,
contentType: 'application/json',
schema: {
description: "Supplier data",
title: "Supplier",
type: apigateway.JsonSchemaType.ARRAY
items: {type: supplierModel}
},
})
And change the "application/json": supplierModel in api to "application/json": supplierModelArray

angular-formly triggering remote errors

How can I trigger error on filed ? Assume we got form consist of name, email, password. We check email uniqness on server side, and server sends object like { email: ['already taken', 'another error' ] etc. How can i tap into the form and trigger those on fields?
Sounds to me like you want to do a async validation of an input field. I assume you wanna make something like this.
For the concrete solution see this Blog
I see - wasn't aware angular-formly..
you can call your validaton service in thre formly asyncValidator and then parse the result and manually set the validation state on the field using scope.fc.$setValidity. The messages can be registered in the validation section.
validators: {
asyncMultiValidator: {
expression: function(viewValue, modelValue, scope) {
$http.get('...validation-url...').success(function(result) {
//assuming the service returns a map of validation results as {'validationName': isValid (boolean) }
angular.foreach(result, function(isValid, validationName) {
scope.fc.$setValidity(validationName, isValid);
});
})
// this dummy validator is always valid
return true;
},
message: 'dummy message - not being used'
}
},
validation: {
messages: {
required: function(viewValue, modelValue, scope) {
return scope.to.label + ' is required'
},
remote: function(viewValue, modelValue, scope) {
return 'some remote error';
}
}

Firebase with Backbone and One to Many Association

So I am attempting to build a one on one chat app with firebase using marionette and backbone. I'm also using the Firebase Backbone bindings. I want there to be many users, each user has many conversation, and each conversation has many messages. Here's how my data looks:
users: {
'user-id-1': {
email: 'test#whatever.com',
conversations: {
'conversation-id-1': true,
'conversation-id-2': true
}
},
'user-id-2': {
email: 'another#email.com',
conversations: {
'conversation-id-1': true,
}
},
'user-id-3': {
email: 'a-third#email.com',
conversations: {
'conversation-id-2': true,
}
}
}
conversations: {
'conversation-id-1': {
sender: 'user-id-1',
receiver: 'user-id-2',
messages: {
'message-id-1': true,
'message-id-2': true
}
},
'conversation-id-2': {
sender: 'user-id-1',
receiver: 'user-id-3',
messages: {
'message-id-3': true,
'message-id-4': true,
'message-id-5': true,
}
}
}
messages: {
'message-id-1': {
sender: 'user-id-1'
body: 'A message'
},
'message-id-2': {
sender: 'user-id-2'
body: 'A response'
},
'message-id-3': {
sender: 'user-id-1'
body: 'An inital message'
},
'message-id-4': {
sender: 'user-id-3'
body: 'Another response'
},
'message-id-5': {
sender: 'user-id-1'
body: 'Goodbye'
},
}
What you can see from this:
User-1 has two different conversations going, each with User-2 and User-3
On a really basic level I am able to fetch all the conversations from the user with a function like so:
class Entities.User extends Backbone.Firebase.Model
urlRoot: 'https://my-app.firebaseio.com/users'
conversations: ->
conversations = new Firebase('https://my-app.firebaseio.com/conversations')
#firebase.child('conversations').on 'child_added', (snap) =>
console.log snap.key()
conversations(snap.key()).once 'value', (value) =>
console.log value.val()
undefined
This will log all of the conversations out when they are retrieved by firebase.
The problems are:
a) There's no real way for me to use a Backbone.Collection here to fetch just this users conversations, let alone the messages for that conversation, is there? I need a collection to pass to Marionettes CollectionView
b) This just seems really messy in general.
Should I be structuring my data differently? I realize there's improvements that could be made to at least the way I am collecting the conversations so I could get an array.
What am I doing wrong? Any advice would be much appreciated.

Resources