Fixes SMS not sending for country codes not supporting alphanumeric sender IDs (#5969)
* don't use alphanumeric sender ID for not support country codes * fix import * rename file * fix spelling mistakes * add twilio phone number to .env file * add SENDER_ID to env variable and create function to get sender id * add NEXT_PUBLIC_SENDER_ID env variable * remove not needed Cal fallback * fix readme * code clean up * code clean up Co-authored-by: CarinaWolli <wollencarina@gmail.com>
This commit is contained in:
parent
56c07ec351
commit
c1bbb9b139
|
@ -85,6 +85,8 @@ SENDGRID_EMAIL=
|
|||
TWILIO_SID=
|
||||
TWILIO_TOKEN=
|
||||
TWILIO_MESSAGING_SID=
|
||||
TWILIO_PHONE_NUMBER=
|
||||
NEXT_PUBLIC_SENDER_ID=
|
||||
|
||||
# This is used so we can bypass emails in auth flows for E2E testing
|
||||
# Set it to "1" if you need to run E2E tests locally
|
||||
|
|
18
README.md
18
README.md
|
@ -419,14 +419,16 @@ following
|
|||
2. Click ‘Get a Twilio phone number’
|
||||
3. Copy Account SID to your .env file into the TWILIO_SID field
|
||||
4. Copy Auth Token to your .env file into the TWILIO_TOKEN field
|
||||
5. Create a messaging service (Develop -> Messaging -> Services)
|
||||
6. Choose any name for the messaging service
|
||||
7. Click 'Add Senders'
|
||||
8. Choose phone number as sender type
|
||||
9. Add the listed phone number
|
||||
10. Leave all other fields as they are
|
||||
11. Complete setup and click ‘View my new Messaging Service’
|
||||
12. Copy Messaging Service SID to your .env file into the TWILIO_MESSAGING_SID field
|
||||
5. Copy your Twilio phone number to your .env file into the TWILIO_PHONE_NUMBER field
|
||||
6. Add your own sender id to the .env file into the NEXT_PUBLIC_SENDER_ID field (fallback is Cal)
|
||||
7. Create a messaging service (Develop -> Messaging -> Services)
|
||||
8. Choose any name for the messaging service
|
||||
9. Click 'Add Senders'
|
||||
10. Choose phone number as sender type
|
||||
11. Add the listed phone number
|
||||
12. Leave all other fields as they are
|
||||
13. Complete setup and click ‘View my new Messaging Service’
|
||||
14. Copy Messaging Service SID to your .env file into the TWILIO_MESSAGING_SID field
|
||||
|
||||
<!-- LICENSE -->
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import dayjs from "@calcom/dayjs";
|
|||
import { defaultHandler } from "@calcom/lib/server";
|
||||
import prisma from "@calcom/prisma";
|
||||
|
||||
import { getSenderId } from "../lib/alphanumericSenderIdSupport";
|
||||
import * as twilio from "../lib/reminders/smsProviders/twilioProvider";
|
||||
import customTemplate, { VariablesType } from "../lib/reminders/templates/customTemplate";
|
||||
import smsReminderTemplate from "../lib/reminders/templates/smsReminderTemplate";
|
||||
|
@ -72,6 +73,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||
? reminder.booking?.attendees[0].timeZone
|
||||
: reminder.booking?.user?.timeZone;
|
||||
|
||||
const senderID = getSenderId(sendTo, reminder.workflowStep.sender);
|
||||
|
||||
let message: string | null = reminder.workflowStep.reminderBody;
|
||||
switch (reminder.workflowStep.template) {
|
||||
case WorkflowTemplates.REMINDER:
|
||||
|
@ -105,12 +108,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|||
break;
|
||||
}
|
||||
if (message?.length && message?.length > 0 && sendTo) {
|
||||
const scheduledSMS = await twilio.scheduleSMS(
|
||||
sendTo,
|
||||
message,
|
||||
reminder.scheduledDate,
|
||||
reminder.workflowStep.sender || "Cal"
|
||||
);
|
||||
const scheduledSMS = await twilio.scheduleSMS(sendTo, message, reminder.scheduledDate, senderID);
|
||||
|
||||
await prisma.workflowReminder.update({
|
||||
where: {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { Dispatch, SetStateAction, useState } from "react";
|
|||
import { Controller, useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
|
||||
import { SENDER_ID } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import {
|
||||
Button,
|
||||
|
@ -68,7 +69,7 @@ export const AddActionDialog = (props: IAddActionDialog) => {
|
|||
mode: "onSubmit",
|
||||
defaultValues: {
|
||||
action: WorkflowActions.EMAIL_HOST,
|
||||
sender: "Cal",
|
||||
sender: SENDER_ID,
|
||||
},
|
||||
resolver: zodResolver(formSchema),
|
||||
});
|
||||
|
@ -166,7 +167,7 @@ export const AddActionDialog = (props: IAddActionDialog) => {
|
|||
<TextField
|
||||
label={t("sender_id")}
|
||||
type="text"
|
||||
placeholder="Cal"
|
||||
placeholder={SENDER_ID}
|
||||
maxLength={11}
|
||||
{...form.register(`sender`)}
|
||||
/>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { useRouter } from "next/router";
|
|||
import { Dispatch, SetStateAction, useMemo, useState } from "react";
|
||||
import { Controller, UseFormReturn } from "react-hook-form";
|
||||
|
||||
import { SENDER_ID } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import useMeQuery from "@calcom/trpc/react/hooks/useMeQuery";
|
||||
|
@ -73,7 +74,7 @@ export default function WorkflowDetailsPage(props: Props) {
|
|||
emailSubject: null,
|
||||
template: WorkflowTemplates.CUSTOM,
|
||||
numberRequired: numberRequired || false,
|
||||
sender: sender || "Cal",
|
||||
sender: sender || SENDER_ID,
|
||||
};
|
||||
steps?.push(step);
|
||||
form.setValue("steps", steps);
|
||||
|
|
|
@ -9,6 +9,7 @@ import { Dispatch, SetStateAction, useRef, useState } from "react";
|
|||
import { Controller, UseFormReturn } from "react-hook-form";
|
||||
import "react-phone-number-input/style.css";
|
||||
|
||||
import { SENDER_ID } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
|
@ -366,7 +367,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
|||
<TextField
|
||||
label={t("sender_id")}
|
||||
type="text"
|
||||
placeholder="Cal"
|
||||
placeholder={SENDER_ID}
|
||||
maxLength={11}
|
||||
{...form.register(`steps.${step.stepNumber - 1}.sender`)}
|
||||
/>
|
||||
|
@ -557,7 +558,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
|||
emailSubject,
|
||||
reminderBody,
|
||||
template: step.template,
|
||||
sender: step.sender || "Cal",
|
||||
sender: step.sender || SENDER_ID,
|
||||
});
|
||||
} else {
|
||||
const isNumberValid =
|
||||
|
@ -596,6 +597,7 @@ export default function WorkflowStepContainer(props: WorkflowStepProps) {
|
|||
reminderBody: reminderBody || "",
|
||||
template: step.template,
|
||||
sendTo: step.sendTo || "",
|
||||
sender: step.sender || SENDER_ID,
|
||||
});
|
||||
setConfirmationDialogOpen(false);
|
||||
}}>
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
import { SENDER_ID } from "@calcom/lib/constants";
|
||||
|
||||
export function getSenderId(phoneNumber?: string | null, sender?: string | null) {
|
||||
const isAlphanumericSenderIdSupported = !noAlphanumericSenderIdSupport.find(
|
||||
(code) => code === phoneNumber?.substring(0, code.length)
|
||||
);
|
||||
|
||||
const senderID = isAlphanumericSenderIdSupported ? sender || SENDER_ID : "";
|
||||
|
||||
return senderID;
|
||||
}
|
||||
|
||||
const noAlphanumericSenderIdSupport = [
|
||||
"+93",
|
||||
"+54",
|
||||
"+374",
|
||||
"+1",
|
||||
"+375",
|
||||
"+32",
|
||||
"+229",
|
||||
"+55",
|
||||
"+237",
|
||||
"+56",
|
||||
"+86",
|
||||
"+57",
|
||||
"+243",
|
||||
"+506",
|
||||
"+53",
|
||||
"+42",
|
||||
"+593",
|
||||
"+20",
|
||||
"+503",
|
||||
"+251",
|
||||
"+594",
|
||||
"+233",
|
||||
"+224",
|
||||
"+245",
|
||||
"+852",
|
||||
"+36",
|
||||
"+91",
|
||||
"+62",
|
||||
"+98",
|
||||
"+972",
|
||||
"+225",
|
||||
"+962",
|
||||
"+7",
|
||||
"+254",
|
||||
"+965",
|
||||
"+996",
|
||||
"+231",
|
||||
"+60",
|
||||
"+52",
|
||||
"+212",
|
||||
"+95",
|
||||
"+674",
|
||||
"+977",
|
||||
"+64",
|
||||
"+505",
|
||||
"+234",
|
||||
"+968",
|
||||
"+507",
|
||||
"+595",
|
||||
"+51",
|
||||
"+63",
|
||||
"+974",
|
||||
"+7",
|
||||
"+250",
|
||||
"+966",
|
||||
"+27",
|
||||
"+82",
|
||||
"+211",
|
||||
"+94",
|
||||
"+249",
|
||||
"+268",
|
||||
"+963",
|
||||
"+886",
|
||||
"+255",
|
||||
"+66",
|
||||
"+216",
|
||||
"+90",
|
||||
"+256",
|
||||
"+971",
|
||||
"+598",
|
||||
"+58",
|
||||
"+84",
|
||||
"+260",
|
||||
];
|
|
@ -6,6 +6,7 @@ import {
|
|||
WorkflowTriggerEvents,
|
||||
} from "@prisma/client";
|
||||
|
||||
import { SENDER_ID } from "@calcom/lib/constants";
|
||||
import type { CalendarEvent } from "@calcom/types/Calendar";
|
||||
|
||||
import { scheduleEmailReminder } from "./emailReminderManager";
|
||||
|
@ -51,7 +52,7 @@ export const scheduleWorkflowReminders = async (
|
|||
step.reminderBody || "",
|
||||
step.id,
|
||||
step.template,
|
||||
step.sender || "Cal"
|
||||
step.sender || SENDER_ID
|
||||
);
|
||||
} else if (
|
||||
step.action === WorkflowActions.EMAIL_ATTENDEE ||
|
||||
|
@ -120,7 +121,7 @@ export const sendCancelledReminders = async (
|
|||
step.reminderBody || "",
|
||||
step.id,
|
||||
step.template,
|
||||
step.sender || "Cal"
|
||||
step.sender || SENDER_ID
|
||||
);
|
||||
} else if (
|
||||
step.action === WorkflowActions.EMAIL_ATTENDEE ||
|
||||
|
|
|
@ -25,7 +25,7 @@ export const sendSMS = async (phoneNumber: string, body: string, sender: string)
|
|||
body: body,
|
||||
messagingServiceSid: process.env.TWILIO_MESSAGING_SID,
|
||||
to: phoneNumber,
|
||||
from: sender,
|
||||
from: sender ? sender : process.env.TWILIO_PHONE_NUMBER,
|
||||
});
|
||||
|
||||
return response;
|
||||
|
@ -39,7 +39,7 @@ export const scheduleSMS = async (phoneNumber: string, body: string, scheduledDa
|
|||
to: phoneNumber,
|
||||
scheduleType: "fixed",
|
||||
sendAt: scheduledDate,
|
||||
from: sender,
|
||||
from: sender ? sender : process.env.TWILIO_PHONE_NUMBER,
|
||||
});
|
||||
|
||||
return response;
|
||||
|
|
|
@ -10,6 +10,7 @@ import dayjs from "@calcom/dayjs";
|
|||
import prisma from "@calcom/prisma";
|
||||
import { Prisma } from "@calcom/prisma/client";
|
||||
|
||||
import { getSenderId } from "../alphanumericSenderIdSupport";
|
||||
import * as twilio from "./smsProviders/twilioProvider";
|
||||
import customTemplate, { VariablesType } from "./templates/customTemplate";
|
||||
import smsReminderTemplate from "./templates/smsReminderTemplate";
|
||||
|
@ -57,6 +58,8 @@ export const scheduleSMSReminder = async (
|
|||
const timeUnit: timeUnitLowerCase | undefined = timeSpan.timeUnit?.toLocaleLowerCase() as timeUnitLowerCase;
|
||||
let scheduledDate = null;
|
||||
|
||||
const senderID = getSenderId(reminderPhone, sender);
|
||||
|
||||
if (triggerEvent === WorkflowTriggerEvents.BEFORE_EVENT) {
|
||||
scheduledDate = timeSpan.time && timeUnit ? dayjs(startTime).subtract(timeSpan.time, timeUnit) : null;
|
||||
} else if (triggerEvent === WorkflowTriggerEvents.AFTER_EVENT) {
|
||||
|
@ -98,7 +101,7 @@ export const scheduleSMSReminder = async (
|
|||
triggerEvent === WorkflowTriggerEvents.RESCHEDULE_EVENT
|
||||
) {
|
||||
try {
|
||||
await twilio.sendSMS(reminderPhone, message, sender);
|
||||
await twilio.sendSMS(reminderPhone, message, senderID);
|
||||
} catch (error) {
|
||||
console.log(`Error sending SMS with error ${error}`);
|
||||
}
|
||||
|
@ -117,7 +120,7 @@ export const scheduleSMSReminder = async (
|
|||
reminderPhone,
|
||||
message,
|
||||
scheduledDate.toDate(),
|
||||
sender
|
||||
senderID
|
||||
);
|
||||
|
||||
await prisma.workflowReminder.create({
|
||||
|
|
|
@ -9,6 +9,7 @@ export const WEBSITE_URL = process.env.NEXT_PUBLIC_WEBSITE_URL || "https://cal.c
|
|||
export const APP_NAME = process.env.NEXT_PUBLIC_APP_NAME || "Cal.com";
|
||||
export const SUPPORT_MAIL_ADDRESS = process.env.NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS || "help@cal.com";
|
||||
export const COMPANY_NAME = process.env.NEXT_PUBLIC_COMPANY_NAME || "Cal.com, Inc.";
|
||||
export const SENDER_ID = process.env.NEXT_PUBLIC_SENDER_ID || "Cal";
|
||||
|
||||
// This is the URL from which all Cal Links and their assets are served.
|
||||
// Use website URL to make links shorter(cal.com and not app.cal.com)
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
deleteScheduledSMSReminder,
|
||||
scheduleSMSReminder,
|
||||
} from "@calcom/features/ee/workflows/lib/reminders/smsReminderManager";
|
||||
import { SENDER_ID } from "@calcom/lib/constants";
|
||||
import { getErrorFromUnknown } from "@calcom/lib/errors";
|
||||
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
@ -154,7 +155,7 @@ export const workflowsRouter = router({
|
|||
action: WorkflowActions.EMAIL_HOST,
|
||||
template: WorkflowTemplates.REMINDER,
|
||||
workflowId: workflow.id,
|
||||
sender: "Cal",
|
||||
sender: SENDER_ID,
|
||||
},
|
||||
});
|
||||
return { workflow };
|
||||
|
@ -469,7 +470,7 @@ export const workflowsRouter = router({
|
|||
step.reminderBody || "",
|
||||
step.id,
|
||||
step.template,
|
||||
step.sender || "Cal"
|
||||
step.sender || SENDER_ID
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -535,7 +536,7 @@ export const workflowsRouter = router({
|
|||
emailSubject: newStep.template === WorkflowTemplates.CUSTOM ? newStep.emailSubject : null,
|
||||
template: newStep.template,
|
||||
numberRequired: newStep.numberRequired,
|
||||
sender: newStep.sender || "Cal",
|
||||
sender: newStep.sender || SENDER_ID,
|
||||
},
|
||||
});
|
||||
//cancel all reminders of step and create new ones (not for newEventTypes)
|
||||
|
@ -647,7 +648,7 @@ export const workflowsRouter = router({
|
|||
newStep.reminderBody || "",
|
||||
newStep.id || 0,
|
||||
newStep.template,
|
||||
newStep.sender || "Cal"
|
||||
newStep.sender || SENDER_ID
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -671,7 +672,7 @@ export const workflowsRouter = router({
|
|||
addedSteps.forEach(async (step) => {
|
||||
if (step) {
|
||||
const newStep = step;
|
||||
newStep.sender = step.sender || "Cal";
|
||||
newStep.sender = step.sender || SENDER_ID;
|
||||
const createdStep = await ctx.prisma.workflowStep.create({
|
||||
data: step,
|
||||
});
|
||||
|
@ -760,7 +761,7 @@ export const workflowsRouter = router({
|
|||
step.reminderBody || "",
|
||||
createdStep.id,
|
||||
step.template,
|
||||
step.sender || "Cal"
|
||||
step.sender || SENDER_ID
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -897,7 +898,7 @@ export const workflowsRouter = router({
|
|||
reminderBody,
|
||||
0,
|
||||
template,
|
||||
sender || "Cal"
|
||||
sender || SENDER_ID
|
||||
);
|
||||
return { message: "Notification sent" };
|
||||
}
|
||||
|
|
|
@ -183,6 +183,7 @@
|
|||
"$TWILIO_TOKEN",
|
||||
"$TWILIO_SID",
|
||||
"$TWILIO_MESSAGING_SID",
|
||||
"$TWILIO_PHONE_NUMBER",
|
||||
"$CRON_API_KEY",
|
||||
"$DAILY_API_KEY",
|
||||
"$DAILY_SCALE_PLAN",
|
||||
|
@ -221,6 +222,7 @@
|
|||
"$NEXT_PUBLIC_APP_NAME",
|
||||
"$NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS",
|
||||
"$NEXT_PUBLIC_COMPANY_NAME",
|
||||
"$NEXT_PUBLIC_SENDER_ID",
|
||||
"$NEXTAUTH_COOKIE_DOMAIN",
|
||||
"$NEXTAUTH_SECRET",
|
||||
"$NEXTAUTH_URL",
|
||||
|
|
Loading…
Reference in New Issue
Block a user