Send Personalised Birthday Emails from Google Sheets Using Apps Script
Remembering birthdays is easy when a script does it for you. Keep a list of contacts with birthdays in a Sheet, and let Apps Script send personalised emails automatically every morning.
Sheet structure
Set up your sheet with these columns:
| A: Name | B: Email | C: Birthday (MM/DD or date) | D: Last Sent Year |
Column D prevents duplicate emails if you run the script multiple times.
Check for birthdays and send emails
functionsendBirthdayEmails(){const sheet =SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();const data = sheet.getDataRange().getValues();const today =newDate();const todayMonth = today.getMonth()+1;const todayDay = today.getDate();const thisYear = today.getFullYear();for(let i =1; i < data.length; i++){const[name, email, birthday, lastSentYear]= data[i];if(!birthday ||!email)continue;const bDate =newDate(birthday);const bMonth = bDate.getMonth()+1;const bDay = bDate.getDate();// Check if today is their birthday and we haven't sent this yearif(bMonth === todayMonth && bDay === todayDay && lastSentYear !== thisYear){sendBirthdayEmail(name, email); sheet.getRange(i +1,4).setValue(thisYear);// Mark as sentLogger.log(`Birthday email sent to ${name} (${email})`);}}}functionsendBirthdayEmail(name, email){const subject =`🎂 Happy Birthday, ${name}!`;const html =` <div style="font-family:sans-serif;max-width:500px;margin:0 auto;text-align:center;">
<h1 style="font-size:48px;">🎂</h1>
<h2 style="color:#1a73e8;">Happy Birthday, ${name}!</h2>
<p style="font-size:16px;color:#444;">
Wishing you a wonderful day filled with joy and celebration.
Hope this year brings you everything you're looking for!
</p>
<p style="color:#888;font-size:13px;margin-top:32px;">
With warm wishes from the team
</p>
</div>
`;GmailApp.sendEmail(email, subject,`Happy Birthday, ${name}!`,{htmlBody: html });}
Handle MM/DD format (no year)
If your birthdays are stored as strings like "03/15" or "March 15":
functionparseBirthday(value){if(!value)returnnull;// Handle MM/DD string formatif(typeof value ==='string'&& value.includes('/')){const[month, day]= value.split('/').map(Number);return{ month, day };}// Handle Date object or full date stringconst d =newDate(value);return{month: d.getMonth()+1,day: d.getDate()};}functioncheckBirthdays(){const sheet =SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();const data = sheet.getDataRange().getValues();const today =newDate();const thisYear = today.getFullYear();for(let i =1; i < data.length; i++){const[name, email, birthdayRaw, lastSentYear]= data[i];const birthday =parseBirthday(birthdayRaw);if(!birthday ||!email)continue;const isBirthday = birthday.month=== today.getMonth()+1&& birthday.day=== today.getDate();if(isBirthday && lastSentYear !== thisYear){sendBirthdayEmail(name, email); sheet.getRange(i +1,4).setValue(thisYear);}}}