1

I'm looking to send out an email (specifically the values entered into a form) from a specific gmail account, and due to platform limitations I have to use client side (i.e. javascript) code to do so. I'm testing the following code, but it seems to be using my personal gmail credentials, rather than the client id I'm trying to specify. What am I doing wrong?

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Base64/1.0.0/base64.min.js"></script>
<script type="text/javascript">
  var CLIENT_ID = 'myclientid.apps.googleusercontent.com';
  var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/gmail/v1/rest"];
  var SCOPES = 'https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.send';
  function handleClientLoad() {
    gapi.load('client:auth2', initClient);
  }
  function initClient() {
    gapi.client.init({
      discoveryDocs: DISCOVERY_DOCS,
      clientId: CLIENT_ID,
      scope: SCOPES
    });
  }

  // ucs-2 string to base64 encoded ascii
  function utoa(str) {
    return window.btoa(unescape(encodeURIComponent(str)));
  }
  // base64 encoded ascii to ucs-2 string
  function atou(str) {
    return decodeURIComponent(escape(window.atob(str)));
  }

  function submitForm(form) {
    var formid = form.id.length>0 ? '('+form.id+') ' : '';
    var bodyText='The form '+formid+'was filled out on '+window.location.href+'\r\n'+
                 'The following values were submitted:';
    for (var i=0;i<form.childElementCount;i++) {
        bodyText += '\r\n'+'\r\n'+form[i].name+'\r\n'+form[i].value;
    }
    var unencodedEmail = 'To: '+form.attributes.getNamedItem('data-submit-to').value+
                         '\r\nSubject: A form '+formid+'was filled out on '+window.location.href+
                         '\r\n'+bodyText;
    try {
        var authInstance = gapi.auth2.getAuthInstance();
        authInstance.signIn({ client_id: CLIENT_ID });
        try {
            var base64EncodedEmail = utoa(unencodedEmail);
            var request = gapi.client.gmail.users.messages.send({
                'userId': 'me',
                'resource': {
                  'message': {
                    'raw': base64EncodedEmail
                  }
                }
              });
            request.execute(function() {/*do post email sending stuff*/});
        } finally {
            authInstance.signOut();
        }
    } finally { 
        return false;//prevent the form from redirecting
    }
  }
</script>

<script async defer src="https://apis.google.com/js/api.js"
  onload="this.onload=function(){};handleClientLoad()"
  onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
1
  • Hey Josh, with EmailJS.com you can connect your Gmail account and then use it to send pre-built email templates using a simple js library (disclosure: I'm one of creators). Hope this helps! Commented Mar 28, 2017 at 13:05

1 Answer 1

1

You cannot use other people's credentials, you need to use your own. If you follow the Javascript Quickstart for Gmail, you'll find out that the credentials will be from your Google mail account. This is the reason we have a thing called OAuth. If Google allowed that, this would be open to exploitation and malign use.

Sign up to request clarification or add additional context in comments.

2 Comments

To be clear, I want to use a single, specific account under my own control. I am aware that in general account impersonation/delegation is a security nightmare, but I was wondering if there was a safe, controlled way to do this. FWIW, it looks like what I am requesting is theoretically possible with a Service account, but even that feels, at best, fraught with pitfalls.
A further thought regarding the Service account idea: DON'T DO IT. Service accounts are designed to be used with compiled or server-side applications, and should not be exposed to end users. It would be very easy to hijack the service account and reuse it for other nefarious purposes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.