简体   繁体   中英

Adding Label to Gmail sent from Nodemailer with GmailAPI

I am using Gmail API, with nodemailer to send an automated email to unread threads. I want to add a label of AutoResponse in Gamil so that the replied mails appear with that labels.

Here is the code for sending the mail

const checkForNewMessages = () => {
    //get message details
  gmail.users.messages.list(
    {
      userId: "me",
      q: `is:unread`,
    },
    async (err, res) => {
      if (err) return console.log("The API returned an error: " + err);

      const messages = res.data.messages;

      if (messages?.length) {
        console.log("New message received!");

        //checking if message unread
        for (const message of messages) {
          const messageDetails = await gmail.users.messages.get({
            userId: "me",
            id: message.id,
          });
          const threadId = messageDetails.data.threadId;
          const threadDetails = await gmail.users.threads.get({
            userId: "me",
            id: threadId,
          });

          const addLabelToThread = await gmail.users.threads.modify({
            userId: "me",
            id: threadId,
            resource: {
              addLabelIds: ["AutoResponse"],
              removeLabelIds: ["INBOX"],
            },
          });

          if (
            !threadDetails.data.messages.some(
              (msg) =>
                msg.labelIds.includes("SENT") &&
                msg.payload.headers.find(
                  (header) =>
                    header.name === "From" &&
                    header.value.includes("mymail@gmail.com")
                )
            )
          ) {
            console.log(
              `New email thread with subject "${
                messageDetails.data.payload.headers.find(
                  (header) => header.name === "Subject"
                ).value
              }" and thread ID ${threadId} received!`
            );

            // Sending a response to new unread Threads
            const transporter = nodemailer.createTransport({
              service: "gmail",
              auth: {
                type: "OAuth2",
                user: "mymail@gmail.com",
                clientId: process.env.CLIENT_ID,
                clientSecret: process.env.CLIENT_SECRET,
                refreshToken: process.env.REFRESH_TOKEN,
                accessToken: oAuth2Client.getAccessToken(),
              },
            });

            const mailOptions = {
              from: "mymail@gmail.com",
              to: messageDetails.data.payload.headers.find(
                (header) => header.name === "From"
              ).value,
              subject:
                "Re: " +
                messageDetails.data.payload.headers.find(
                  (header) => header.name === "Subject"
                ).value,
              text: "Thank you for your message. I will respond as soon as I am available",
            };

            transporter.sendMail(mailOptions, async (err, info) => {
              if (err) {
                console.log(err);
              } else {
                console.log(
                  `Automatic response sent to ${
                    messageDetails.data.payload.headers.find(
                      (header) => header.name === "From"
                    ).value
                  }: ${info.response}`
                );
                addLabelToThread();
              }
            });

          } else {
            console.log(
              `Email thread with thread ID ${threadId} already has a reply from you.`
            );
          }
        }
      } else {
        console.log("No new messages.");
      }
    }
  );
};

I tried the addLabelToThread function, but doesn't seem to work. Giving this error to be specific

 error: {
        code: 400,
        message: 'Invalid label: SENT',
        errors: [
          {
            message: 'Invalid label: SENT',
            domain: 'global',
            reason: 'invalidArgument'
          }
        ],
        status: 'INVALID_ARGUMENT'
      }

I have a workaround for this. The proposed solution is implemented using GMAIL Node.js SDK .

Observation -

Whenever we send new email using send() function, it by default adds a SENT Label to it.

When we try to remove it using modify() it will throw an error such as

 {
      message: 'Invalid label: SENT',
      domain: 'global',
      reason: 'invalidArgument'
 }

So, for attaching a new label to a sent email we can execute following code just after we sent the email.

  const updatedGmail = await gmail.users.messages.modify({
        userId: "me", // if user is authenticated
        id: res.data.id, // id of email
        requestBody: {
            addLabelIds: ["Label_5091976681185583145"]
        }
    })

This will add another label to sent email with SENT label. Although, this is not the way most people want it but I did it this way and it works for me

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM