{ "kind": "open-flow-workflow", "version": 1, "name": "Send a Localized Welcome Email by IP", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_567095ff7ad4eecf": { "name": "Enter IP and recipient", "kind": "start", "inputDefs": [ { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "ip" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "email" } ] }, "n_af5a64e49749c08c": { "inputs": { "ip": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_567095ff7ad4eecf", "output": "ip" } ] } }, "name": "Prepare IP lookup", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "ip" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "body" } ], "name": "Prepare IP lookup", "moduleId": "n_285db7a3349f335e", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_aeca45ff591e0eb9": { "inputs": { "url": { "kind": "value", "value": "https://api.uproc.io/api/v2/process" }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_af5a64e49749c08c", "output": "body" } ] }, "auth.username": { "kind": "unset" }, "auth.password": { "kind": "unset" } }, "name": "Look up IP location", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.username" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.password" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Look up IP location", "executor": { "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [] }, "bodyFormat": "json", "authentication": { "type": "basic" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_2570fb1c58a49892": { "inputs": { "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_aeca45ff591e0eb9", "output": "body" } ] }, "previousState": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2570fb1c58a49892", "output": "state" } ] }, "email": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_567095ff7ad4eecf", "output": "email" } ] }, "from": { "kind": "value", "value": "sender@example.com" }, "response": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_075cf529276a41d4", "output": "body" } ] } }, "name": "Prepare next welcome email", "kind": "task", "task": { "inputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": true, "handle": "previousState" }, { "jsonSchema": {}, "nullable": true, "handle": "response" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "email" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "from" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "state" }, { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "to" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "from" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "subject" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "message" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "count" }, { "jsonSchema": { "type": "array" }, "nullable": false, "handle": "responses" } ], "name": "Prepare next welcome email", "moduleId": "n_0efaab32259edc05", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_26112ed468582b42": { "inputs": {}, "name": "More results?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "more", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_2570fb1c58a49892", "output": "more" } }, "operator": "isTrue" } ] } ] } ] }, "n_7593e7a484cc2f89": { "inputs": { "to": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2570fb1c58a49892", "output": "to" } ] }, "from": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2570fb1c58a49892", "output": "from" } ] }, "subject": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2570fb1c58a49892", "output": "subject" } ] }, "message": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2570fb1c58a49892", "output": "message" } ] }, "region": { "kind": "value", "value": "us-east-1" }, "accessKeyId": { "kind": "unset" }, "secretAccessKey": { "kind": "unset" }, "sessionToken": { "kind": "value", "value": null } }, "name": "Sign SES request", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "to" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "from" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "subject" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "message" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "region" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "accessKeyId" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "secretAccessKey" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "sessionToken" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "authorization" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "amzDate" }, { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "body" } ], "name": "Sign SES request", "moduleId": "n_464049c050e09fa8", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_075cf529276a41d4": { "inputs": { "url": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_7593e7a484cc2f89", "output": "url" } ] }, "header.Content-Type": { "kind": "value", "value": "application/json" }, "header.Authorization": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_7593e7a484cc2f89", "output": "authorization" } ] }, "header.X-Amz-Date": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_7593e7a484cc2f89", "output": "amzDate" } ] }, "header.X-Amz-Security-Token": { "kind": "value", "value": null }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_7593e7a484cc2f89", "output": "body" } ] } }, "name": "Send with Amazon SES", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "header.Content-Type" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "header.Authorization" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "header.X-Amz-Date" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "header.X-Amz-Security-Token" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "body" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Send with Amazon SES", "executor": { "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [ "Content-Type", "Authorization", "X-Amz-Date", "X-Amz-Security-Token" ] }, "bodyFormat": "text", "authentication": { "type": "none" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } }, "n_6b71e1c34e8cfa25": { "name": "Emails sent", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "count" }, { "jsonSchema": { "type": "array" }, "nullable": false, "handle": "responses" } ], "outputMappings": { "count": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2570fb1c58a49892", "output": "count" } ] }, "responses": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2570fb1c58a49892", "output": "responses" } ] } } } }, "edges": [ { "source": "n_567095ff7ad4eecf", "target": "n_af5a64e49749c08c" }, { "source": "n_af5a64e49749c08c", "target": "n_aeca45ff591e0eb9" }, { "source": "n_aeca45ff591e0eb9", "target": "n_2570fb1c58a49892" }, { "source": "n_2570fb1c58a49892", "target": "n_26112ed468582b42" }, { "source": "n_26112ed468582b42", "target": "n_7593e7a484cc2f89", "sourceHandle": "more" }, { "source": "n_7593e7a484cc2f89", "target": "n_075cf529276a41d4" }, { "source": "n_075cf529276a41d4", "target": "n_2570fb1c58a49892" }, { "source": "n_26112ed468582b42", "target": "n_6b71e1c34e8cfa25", "sourceHandle": "otherwise" } ] } }, "modules": { "n_285db7a3349f335e": { "name": "Prepare IP lookup", "imports": [], "source": "export default function prepare({ip}){if(typeof ip!=='string'||!ip)throw Error('Enter an IP address');return{body:{processor:'get-location-by-ip',params:{ip}}}}\n" }, "n_0efaab32259edc05": { "name": "Prepare next welcome email", "imports": [], "source": "export default function next({body,previousState,response,email,from}){const rows=Array.isArray(body)?body:[body],list=[...rows.filter(x=>x?.message?.country_code==='ES'),...rows.filter(x=>x?.message?.country_code!=='ES')],state=previousState??{index:0,responses:[]};if(previousState){state.responses.push(response);state.index++}if(state.index>list.length)throw Error('Invalid result state');if(state.index===list.length)return{state,more:false,to:email,from,subject:'unused',message:'unused',count:state.index,responses:state.responses};const spanish=list[state.index]?.message?.country_code==='ES';return{state,more:true,to:email,from,subject:spanish?'Bienvenido a bordo':'Welcome aboard',message:spanish?'Hola,\\n\\n”Gracias por registrarte!':'Hi,\\n\\nThank you for your signup!',count:state.index,responses:state.responses}}\n" }, "n_464049c050e09fa8": { "name": "Sign SES request", "imports": [], "source": "import{createHash,createHmac}from'node:crypto';\nexport default function sign({to,from,subject,message,region,accessKeyId,secretAccessKey,sessionToken}){for(const [name,v]of Object.entries({to,from,region,accessKeyId,secretAccessKey}))if(typeof v!=='string'||!v)throw Error('Configure '+name);if(!/^[a-z]{2}(?:-[a-z]+){1,2}-[0-9]+$/.test(region))throw Error('Invalid AWS region');const host='email.'+region+'.amazonaws.com'+(region.startsWith('cn-')?'.cn':''),path='/v2/email/outbound-emails',body=JSON.stringify({FromEmailAddress:from,Destination:{ToAddresses:[to]},Content:{Simple:{Subject:{Data:subject,Charset:'UTF-8'},Body:{Text:{Data:message,Charset:'UTF-8'}}}}}),timestamp=new Date().toISOString().replace(/[:-]|\\.\\d{3}/g,''),date=timestamp.slice(0,8),headers={'content-type':'application/json',host,'x-amz-date':timestamp,...(sessionToken?{'x-amz-security-token':sessionToken}:{})},names=Object.keys(headers).sort(),signedHeaders=names.join(';'),canonicalHeaders=names.map(k=>k+':'+headers[k].trim().replace(/\\s+/g,' ')+'\\n').join(''),hash=x=>createHash('sha256').update(x).digest('hex'),hmac=(k,v)=>createHmac('sha256',k).update(v).digest(),scope=date+'/'+region+'/ses/aws4_request',canonical=['POST',path,'',canonicalHeaders,signedHeaders,hash(body)].join('\\n'),toSign=['AWS4-HMAC-SHA256',timestamp,scope,hash(canonical)].join('\\n'),key=hmac(hmac(hmac(hmac('AWS4'+secretAccessKey,date),region),'ses'),'aws4_request'),sig=createHmac('sha256',key).update(toSign).digest('hex');delete headers.host;headers.authorization='AWS4-HMAC-SHA256 Credential='+accessKeyId+'/'+scope+', SignedHeaders='+signedHeaders+', Signature='+sig;return{url:'https://'+host+path,authorization:headers.authorization,amzDate:timestamp,body}}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }