Send Emails from Gmail to Discord Channel

0xkoji - Jan 25 '22 - - Dev Community

I created a Discord server for an alumni’s mailing list since many people asked “Do we have a Slack group or a Discord server?” and there wouldn’t be any clear answers to the question.

Recently, I wrote a simple script to post emails about job hunting to our Discord server because I created a Discord server to make information more accessible and traceable for people on the list.

The steps for doing that are very simple because we can use Google Apps Script to access gmail without any complicated configuration. One thing you should know is that you must have a permission to add webhooks to a channel. If you don’t have it, there will be two ways to solve the permission issue. One is to request the permission to a Discord server owner or admin and the other is to create your own Discord server which is super easy.

Step 1. Create a channel (if you don’t have a channel)

Step 2. Create a webhook and get token

Step 3. Add a webhook and token as project properties to Google Apps Script

Step 4. Write a script

Step 5. Set a trigger (time driven)

Step 1. Create a channel

Create a new channel if you need it.

Step 2. Create a webhook and get token

This step is very easy because you just need to do the followings.

  1. Click Edit channel button
  2. Select Integrations and Click webhooks
  3. Click New Webhook to create a new one

Step 3. Add webhook and token as project properties to Google Apps Script

Actually, this step should be optional because the current Google Apps Script editor doesn’t offer a way to access project properties. So we need to switch the editor from the current to the classic version temporarily. So if you don’t want to switch the editor, you can hard -code webhook and token in your script. I prefer to use environment var instead of hard-coding.

This step is totally up to you.

  1. Click Use classic editor
  2. Click File → Project properties
  3. Select Script properties tab and add rows for a webhook and token

script properties

Step 4 Write a script

The following is what I use right now (actually I changed a couple of lines for this post).

I think the code itself will be needed to improve the performance because this code will take almost 90 seconds to finish the process. Especially, calling sendDiscord from loop isn’t good lol but I leave this because currently the mailing list isn’t received many job emails lol.

There is one thing you should keep in mind that Discord has a limitation that a free user cannot post more than 2000 characters.

function postDiscord(postMsg) {
  const props = PropertiesService.getScriptProperties();
  const webhooks = props.getProperty("WEBHOOKS"); // get value from project properties
  const token = props.getProperty("TOKEN");
  const channel = 'jobs' // channel name
  const parse = 'full';
  const method = 'post';

  const payload = {
    'token': token,
    'channel': channel,
    'content': postMsg,
    'parse': parse,
  };

  const params = {
    'method': method,
    'payload': payload,
    'muteHttpExceptions': true,
  };
  response = UrlFetchApp.fetch(webhooks, params);
}

function sendMailsToDiscord() {
  const searchQuery = 'label:mailinglist@lists.example.com and subject:job';
  const dt = new Date();
  const checkSpan = 30;
  dt.setMinutes(dt.getMinutes() - checkSpan);

  const threads = GmailApp.search(searchQuery);
  const msgs = GmailApp.getMessagesForThreads(threads);
  for(let i =0; i<msgs.length; i++) {
    const lastMsgDt = threads[i].getLastMessageDate();

    if(lastMsgDt.getTime() < dt.getTime()) {
      break;
    }

    for(let j =0; j<msgs[i].length; j++) {
      const msgDate = msgs[i][j].getDate();
      // const msgBody = msgs[i][j].getBody(); // html
      const msgBody = msgs[i][j].getPlainBody();
      const subject = msgs[i][j].getSubject()
      const postMsg = "From mailing list" + "\n" +
          Utilities.formatDate(msgDate, 'America/New_York', 'MM/DD/yyyy hh:mm:ss') + "\n" +
              "Title:" + subject + "\n" +
              "[hr]" +
               msgBody;
      console.log(`chars: ${postMsg.length}`);
      // The limit is 2000 characters
      if(postMsg.length > 2000) {
        const stopPos = 1900; // 
        const msg =  "`This message is more than 2000 chars so I cannot post the entire message. Sorry.`";
        postMsg = postMsg.substring(0, stopPos) + "\n" + msg
      }
      console.log(postMsg);
      console.log('===================================');
      console.log(`chars: ${postMsg.length}`);
      console.log('===================================');
      postDiscord(postMsg);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 5. Set a trigger (time driven)

Click Timer icon and click Add Trigger in the right bottom.

In this case, select sendMailsToDiscord , Head and Time-driven then choose Minutes timer and Every 30 minutes since we set 30 minutes as check span. If you want to run the script, every 24 hours, you will need to update checkspan and select Day timer then select time from the list.

trigger settings

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player