אתמול פשוט נתקלתי באמצע שיטוט בגוגל במילים ContactsApp, ואז נצנץ לי הרעיון פשוט להשתמש באנשי הקשר של גוגל כדי לשמור רשימת תפוצה של מיילים (אני מדבר על הבלוג הזה).

במקום להתפזר על פני כלים (כגון לשמור את הרשימה דרך ghost - הפלטפורמת בלוגים הנוכחית, או דרך mailchimp וכדו') אפשר לשמור את כל אנשי הקשר הרצויים באנשי קשר גוגל, להקצות להם תווית על מנת לסנן אותם בקלות משאר אנשי הקשר, וזהו. וכל זה על ידי סקריפט פשוט, 'ללא מגע יד אדם'..

המעלה העיקרית בזה היא שברגע שיש לי רשימה כזו באנשי הקשר - אני כבר מבצע את שליחת הניוזלטרים דרך ג'ימייל (דרך גוגל סקריפט, כדי לבצע bulk messaging. או למתנסחים - merge mail) לכל הכתובות שבתווית המסוימת הזו ברגע אחד (רק צריך לזכור את ההגבלה של גוגל עד 150 הודעות יוצאות ביום מהסקריפט).

חשבתי איך לקבל את הנתונים מהמשתמש - והחלטתי ללכת פשוט על doGet - שזה בעצם מה שאחראי על תפקוד הסקריפט כ-web app - אפליקציית ווב. ההבדל הבסיסי בין סקריפט רגיל שנמצא אצלי בספריית הסקריפטים לבין סקריפט שנפרס כ-web app - הוא שעם web app ניתן להתממשק (גם אנשים אחרים ולא רק אני) ולהתממסר איתו בפרוטוקול http ממש כמו אתר אינטרנט.

כשפורסים גוגל סקריפט ל-web app - מקבלים כתובת יחודית לאפליקציית הווב שנוצרה. הפונקציה doGet מגדירה את האירועים שהסקריפט יבצע במקרה של גישה ישירה (GET) לכתובת הסקריפט.

זה הקוד שבו אני משתמש בגוגל סקריפט'ס, הסבר לאחר מכן:

function doGet(e) {
  let email = e.parameters.email
  let name = e.parameters.name
  let method = e.parameters.method
  const validate = validateemail(email)
  if (validate === false) {
    Logger.log(`fake mail submitted...`)
    let result = { email: false, existed: false, created: false }
    return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
  }
  if (method == 'remove') {
    let contact = ContactsApp.getContact(email)
    if (!contact) {
      let result = { removed: false }
      return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
    } else {
      contact.deleteContact()
      Logger.log(`user remove himself from list`)
      let result = { removed: true }
      return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
    } 
  }
  let found = ContactsApp.getContact(email)
  if (!found) {
    Logger.log(`address: ${email}. address not found.. creating contact, naming ${name}`)
    var group = ContactsApp.getContactGroup('בלוג')
    ContactsApp.createContact(name, '', email).addToGroup(group)
    let result = { email: true, existed: false, created: true}
    return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
  } else {
    Logger.log(`address: ${email}. found in contacts, changing to ${name}`)
    found.setFullName(name)
    let result = { email: true, existed: true, created: false}
    return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
  }
}

את הכתובת וההוראות פעולה אני מקבל מהפרמטרים שנשלחו ב-URL, יש פרמטר של שם (name) של כתובת (email) ושל שיטת הפעולה הדרושה (מחיקה של המייל מהרשימה או הוספה של מייל לרשימה).

פרמטרים ב-URL זה פשוט לכתוב בסוף הכתובת - סימן שאלה ? ואז פרמטר עם ערך. לדוגמא אם שם האתר הוא example.com ואני רוצה לשלוח לו בקשה עם הפרמטר morning=true - פשוט שולחים בקשה לכתובת example.com?morning=true.
אם רוצים להכניס כמה פרמטרים יש להפריד ביניהם עם &, ככה:
example.com?morning=true&night=false

לאחר קבלת הפרטים מהבקשה, הסקריפט בודק אם המייל שנשלח הוא אכן כתובת מייל. את זה הוא בודק מול regex שבודק מיילים. זה הפונקציה:

function validateemail(email) {
  const emailregex = /^[A-z0-9._%+-]+@[A-z0-9.-]+\.[A-z]{2,}$/
  return emailregex.test(email)
}

אם הערך ששולחים אליה תואם למבנה החוקי של כתובת מייל - היא מחזירה תשובה true, אחרת - false על פי תנאי זה (במקרה ש-false) הסקריפט עוצר ומחזיר תשובה למבקש עם פירוט בתוך ה-JSON של התשובה - שהמייל מזוייף:

if (validate === false) {
    Logger.log(`fake mail submitted...`)
    let result = { email: false, existed: false, created: false }
    return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
  }

כעת הבדיקה היא אם השיטה (method) היא remove - כלומר שימוש בסקריפט כדי למחוק אימייל מרשימת התפוצה -

if (method == 'remove') {
    let contact = ContactsApp.getContact(email)
    if (!contact) {
      let result = { removed: false }
      return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
    } else {
      contact.deleteContact()
      Logger.log(`user remove himself from list`)
      let result = { removed: true }
      return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
    } 
  }

בהתחלה יש בדיקה אם קיים באמת כזה אימייל ברשימה (if (!contact) אם המשתנה של בדיקת האיש קשר ברשימת אנשי הקשר הוא undefined - סימן שאין איש קשר כזה), ואם יש הוא עובר תהליך מחיקה.

let found = ContactsApp.getContact(email)
  if (!found) {
    Logger.log(`address: ${email}. address not found.. creating contact, naming ${name}`)
    var group = ContactsApp.getContactGroup('בלוג')
    ContactsApp.createContact(name, '', email).addToGroup(group)
    let result = { email: true, existed: false, created: true}
    return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
  } else {
    Logger.log(`address: ${email}. found in contacts, changing to ${name}`)
    thiss.setFullName(name)
    let result = { email: true, existed: true, created: false}
    return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JAVASCRIPT)
  }

כעת הסקריפט בודק (אם הגיע לכאן, זה רק במקרה שהשיטה שנבחרה בכתובת היא להוסיף כתובת אימייל למאגר) אם לא קיימת כתובת אימייל כמו זו שהוזנה, באנשי הקשר. אם לא קיימת - הוא יוצר איש קשר חדש עם הפרטים שהתקבלו + מחיל עליו את התווית המוגדרת.

אם המייל נמצא במאגר - מנסה לשנות פשוט את השם כפי שהוזן הפעם.


כדי לשלב את הסקריפט הזה בצורה פעילה באתר, שילבתי מודל שמבקש מייל + שם, ובלחיצה על כפתור השליחה ('הרשמה') - מוכנס התוכן של תיבות הטקסט (של השם + המייל) לכתובת URL של הסקריפט, עם הפרמטרים המתאימים.

אפשר להסתכל ב-console של הדפדפן ולראות את התקשורת מול הסקריפט, והתשובות שלו לקריאות.


מה שרואים בפוסט הזה זה דבר ראשון - שימוש בסיסי בגוגל סקריפט כ-web app, הפעם באופן של doGet.
השימוש בגוגל סקריפט כאפליקציית ווב, מעצים את הפונקציונליות של הסקריפט שלכם ובעצם פותח את הסקריפט להתממשקות מול כל webhook וכל האינטרנט, בעצם.

זה יכול להיות כלי שימושי ובסיסי בכל תהליך שקשור לאוטומציה באפליקציות ווב (אכתוב כאן בל"נ פוסט איך אני משתמש בזה גם כדי לשלוח התראות מייל בצורה אוטומטית ובקלות. דוגמא אחת).


קצת מ"מ לפונקציות עיקריות בקוד:


אם יש לכם איזו שאלה ❔✨ או כל תגובה 💬, הארה 💡 והערה ❕ שהיא על הפוסט - אשמח מאוד! אם תכתבו אותה בהערות כאן למטה
פשוט להתחבר עם חשבון גיטהב ולהגיב 🎉