@@ -28,7 +28,14 @@ import { rawIngestMethod } from "../extensions/contact-loaders";
2828
2929import { Lambda } from "@aws-sdk/client-lambda" ;
3030import { getSignedUrl } from "@aws-sdk/s3-request-presigner" ;
31- import { GetObjectCommand , S3 } from "@aws-sdk/client-s3" ;
31+ import {
32+ CreateBucketCommand ,
33+ HeadBucketCommand ,
34+ GetObjectCommand ,
35+ waitUntilBucketExists ,
36+ S3Client ,
37+ PutObjectCommand
38+ } from "@aws-sdk/client-s3" ;
3239import { SQS } from "@aws-sdk/client-sqs" ;
3340import Papa from "papaparse" ;
3441import moment from "moment" ;
@@ -861,46 +868,106 @@ export async function exportCampaign(job) {
861868 ( process . env . AWS_ACCESS_KEY_ID && process . env . AWS_SECRET_ACCESS_KEY )
862869 ) {
863870 try {
864- const s3bucket = new S3 ( {
865- // The transformation for params is not implemented.
866- // Refer to UPGRADING.md on aws-sdk-js-v3 for changes needed.
867- // Please create/upvote feature request on aws-sdk-js-codemod for params.
868- params : { Bucket : process . env . AWS_S3_BUCKET_NAME }
871+ const client = new S3Client ( {
872+ region : process . env . AWS_REGION
869873 } ) ;
874+ const bucketName = process . env . AWS_S3_BUCKET_NAME ;
875+
876+ try {
877+ // Check if the S3 bucket already exists
878+ const verifyBucketCommand = new HeadBucketCommand ( {
879+ Bucket : bucketName
880+ } ) ;
881+ await client . send ( verifyBucketCommand ) ;
882+
883+ console . log ( `S3 bucket "${ bucketName } " already exists.` ) ;
884+ } catch ( error ) {
885+ if ( error . name === "NotFound" ) {
886+ console . log (
887+ `S3 bucket "${ bucketName } " not found. Creating a new bucket.`
888+ ) ;
889+
890+ try {
891+ // Create the S3 bucket
892+ const createBucketCommand = new CreateBucketCommand ( {
893+ Bucket : bucketName
894+ } ) ;
895+ await client . send ( createBucketCommand ) ;
896+
897+ console . log ( `S3 bucket "${ bucketName } " created successfully.` ) ;
898+ } catch ( createError ) {
899+ console . error (
900+ `Error creating bucket "${ bucketName } ":` ,
901+ createError
902+ ) ;
903+ }
904+ } else {
905+ console . error ( "Error checking bucket existence:" , error ) ;
906+ }
907+ }
908+
909+ // verifies that the bucket exists before moving forward
910+ // if for some reason this fails, Spoke defensively deletes the job
911+ await waitUntilBucketExists (
912+ { client, maxWaitTime : 15 } ,
913+ { Bucket : bucketName }
914+ ) ;
915+
870916 const campaignTitle = campaign . title
871917 . replace ( / / g, "_" )
872918 . replace ( / \/ / g, "_" ) ;
873919 const key = `${ campaignTitle } -${ moment ( ) . format (
874920 "YYYY-MM-DD-HH-mm-ss"
875921 ) } .csv`;
876922 const messageKey = `${ key } -messages.csv` ;
877- let params = { Key : key , Body : campaignCsv } ;
878- await s3bucket . putObject ( params ) ;
879- params = { Key : key , Expires : 86400 } ;
880- const campaignExportUrl = await await getSignedUrl ( s3bucket , new GetObjectCommand ( params ) , {
881- expiresIn : "/* add value from 'Expires' from v2 call if present, else remove */"
882- } ) ;
883- params = { Key : messageKey , Body : messageCsv } ;
884- await s3bucket . putObject ( params ) ;
885- params = { Key : messageKey , Expires : 86400 } ;
886- const campaignMessagesExportUrl = await await getSignedUrl ( s3bucket , new GetObjectCommand ( params ) , {
887- expiresIn : "/* add value from 'Expires' from v2 call if present, else remove */"
888- } ) ;
923+ let params = { Key : key ,
924+ Body : campaignCsv ,
925+ Bucket : bucketName } ;
926+ await client . send ( new PutObjectCommand ( params ) ) ;
927+ params = { Key : key ,
928+ Expires : 86400 ,
929+ Bucket : bucketName } ;
930+ const campaignExportUrl = await getSignedUrl ( client , new GetObjectCommand ( params ) ) ;
931+ params = { Key : messageKey ,
932+ Body : messageCsv ,
933+ Bucket : bucketName } ;
934+ await client . send ( new PutObjectCommand ( params ) ) ;
935+ params = { Key : messageKey ,
936+ Expires : 86400 ,
937+ Bucket : bucketName } ;
938+ const campaignMessagesExportUrl = await getSignedUrl ( client , new GetObjectCommand ( params ) ) ;
889939 exportResults . campaignExportUrl = campaignExportUrl ;
890940 exportResults . campaignMessagesExportUrl = campaignMessagesExportUrl ;
891941
892- await sendEmail ( {
893- to : user . email ,
894- subject : `Export ready for ${ campaign . title } ` ,
895- text : `Your Spoke exports are ready! These URLs will be valid for 24 hours.
896- Campaign export: ${ campaignExportUrl }
897- Message export: ${ campaignMessagesExportUrl } `
898- } ) . catch ( err => {
899- log . error ( err ) ;
900- log . info ( `Campaign Export URL - ${ campaignExportUrl } ` ) ;
901- log . info ( `Campaign Messages Export URL - ${ campaignMessagesExportUrl } ` ) ;
902- } ) ;
903- log . info ( `Successfully exported ${ id } ` ) ;
942+ // extreme check on email set-up
943+ if ( (
944+ process . env . EMAIL_FROM &&
945+ process . env . EMAIL_HOST &&
946+ process . env . EMAIL_HOST_PASSWORD &&
947+ process . env . EMAIL_HOST_PORT &&
948+ process . env . EMAIL_HOST_USER ) ||
949+ (
950+ process . env . MAILGUN_DOMAIN &&
951+ process . env . MAILGUN_SMTP_LOGIN &&
952+ process . env . MAILGUN_SMTP_PASSWORD &&
953+ process . env . MAILGUN_SMTP_PORT &&
954+ process . env . MAILGUN_SMTP_SERVER &&
955+ process . env . MAILGUN_PUBLIC_KEY
956+ )
957+ ) {
958+ await sendEmail ( {
959+ to : user . email ,
960+ subject : `Export ready for ${ campaign . title } ` ,
961+ text : `Your Spoke exports are ready! These URLs will be valid for 24 hours.
962+ Campaign export: ${ campaignExportUrl }
963+ Message export: ${ campaignMessagesExportUrl } `
964+ } ) . catch ( err => {
965+ log . error ( err ) ;
966+ log . info ( `Campaign Export URL - ${ campaignExportUrl } ` ) ;
967+ log . info ( `Campaign Messages Export URL - ${ campaignMessagesExportUrl } ` ) ;
968+ } ) ;
969+ log . info ( `Successfully exported ${ id } ` ) ;
970+ }
904971 } catch ( err ) {
905972 log . error ( err ) ;
906973 exportResults . error = err . message ;
@@ -927,7 +994,7 @@ export async function exportCampaign(job) {
927994 log . debug ( campaignCsv ) ;
928995 log . debug ( messageCsv ) ;
929996 }
930- if ( exportResults . campaignExportUrl ) {
997+ if ( exportResults . campaignExportUrl || exportResults . error ) {
931998 exportResults . createdAt = String ( new Date ( ) ) ;
932999 await cacheableData . campaign . saveExportData ( campaign . id , exportResults ) ;
9331000 }
0 commit comments