Jump to content

JLG

Members
  • Content Count

    8
  • Joined

  • Last visited

Posts posted by JLG


  1. 4 minutes ago, JLG said:

    thanks a million.

    I now got it to work. the main points seem to be  'https://www.googleapis.com/upload/gmail/v1/users/' + gOAuth2.email + '/messages/send'; and  HTTP.Headers.Add('Accept: application/json');

    it now works.

    however when i try with an attachment - it does send, but the receiver does not get it as an attachment, but a load of base64 text within the email.

    any further ideas?

    I really appreciate your help.

    I really sorted it now.

    I needed the following line

    IdMessage.ContentType := 'multipart/mixed';

     

    phew.

    thanks to all of you out there!!

     


  2. On 12/18/2021 at 8:26 PM, rvk said:

    I just tested your messsage.txt and it works for me. I can create a draft with that message but I can also directly send it (because I have both draft and send access in my app approval).


    This is my code. (Although I would remove the headers From, Reply-To and Date because those would be added automatically. It doesn't hurt when you add them but they are NOT used. From is always the address of the default sender in gmail and Reply-To is always the gmail account and Date is always now.)

     

     

    Looking at your code I now do see a difference with my code.

    You are using Url := 'https://gmail.googleapis.com/gmail/v1/users/' + emailFrom + '/messages/send';

    I'm using Url := 'https://www.googleapis.com/upload/gmail/v1/users/' + gOAuth2.email + '/messages/send';

     

    You need to use the Upload URI, for media upload requests to post this as raw message.

    See here https://developers.google.com/gmail/api/reference/rest/v1/users.messages/send

    There is a difference with /gmail/v1 and /upload/gmail/v1.

     

    If I use your Url I also get an invalid JSON error message 400.

    So use the other Url and it should be fine.

     

    thanks a million.

    I now got it to work. the main points seem to be  'https://www.googleapis.com/upload/gmail/v1/users/' + gOAuth2.email + '/messages/send'; and  HTTP.Headers.Add('Accept: application/json');

    it now works.

    however when i try with an attachment - it does send, but the receiver does not get it as an attachment, but a load of base64 text within the email.

    any further ideas?

    I really appreciate your help.


  3. On 12/16/2021 at 4:35 PM, Remy Lebeau said:

    TIdMessage creates RFC822-style emails.  Do note, however, that the TIdMessage.SaveTo...() methods are designed for SMTP usage, and so will escape emails per SMTP dot-transparency guidelines.  So, to use TIdMessage emails in other protocols, be sure to use the overloaded SaveTo...() methods provided by the TIdMessageHelper unit, which adds an AUseDotTransparency parameter that you can set to False to disable that escaping.

     

    https://www.indyproject.org/2015/07/30/new-tidmessage-helper/

    I did try what you said by doing this code IdMessage.SaveToStream(MS,False,false); this resolves the dottransparency. but still not working. I enclose the txt file of the MS saved as file (I just changed the email address to xxxx to protect privacy)

    I do not know what is wrong, other than perhaps not the right json format for gmail ? I tried encoding base64... not resolved..

    messsage.txt


  4. On 12/16/2021 at 10:06 PM, Geoffrey Smith said:

    I believe the problem with your code is you are not base64url encoding the message.  If you have Delphi 11, you could add the code fragment below to your code and I think it should work.

     

     

    uses System.NetEncoding;

     

    var

      MSEncoded : TStringStream;

    begin

            MSEncoded := TStringStream.Create;

            IdMessage.SaveToStream(MS);

            TNetEncoding.Base64URL.Encode(MS, MSEncoded);

     

    end;

     

    I am afraid I still get a "bad request" response


  5. in order to use the drafts folder of gmail, you need permission. gmail does not allow apps permission to drafts if all they need is to send emails. they insist to use https://gmail.googleapis.com/gmail/v1/users/' + emailFrom +/messages/send  instead.

    if i had access to drafts, then I could use the smtp component. this works well, but the google team complained to me that they don't allow this as I only require to send email, so no access to smtp.

    the code using synapse above is using smtp. when I experimented with smtp, I did not need JSON as you say correctly. problem is now that I am attempting to email directly, the code above wont work.

    I tried adding the header accept json and mmime type as suggested, but to no avail...

    gmail staff are incredibly unhelpful. they refuse to support delphi questions. they have sample code for other platforms(see https://developers.google.com/gmail/api/quickstart/js). I just cant get code working for delphi.

    does anyone there have a simple send with attachment code using delphi for gmail without smtp but using REST?


  6. thanks foir your reply.

    the following is based on your existing code for getting token

     

    function TgmailFrm.Sendemail(FromName, emailFrom, emailRecip, emailSubject,
      emailBody, emailAttach: string; Quietly: Boolean): Boolean;


    var
      HTTP: TIdHTTP;
      Response: TStringList;
      Url, s: STring;
      Base64: TBase64Encoding;

      IdMessage: TIdMessage;
      MailBuilder: TIdMessageBuilderPlain;
      xoauthSASL: TIdSASLListEntry;
      MS: TStringStream;

      fIdSSLIOHandlerSocketOpenSSL: TIdSSLIOHandlerSocketOpenSSL;
    begin

      result := False;

      if not SetupAuthenticator or not HasSavedToken
      then
      begin
        /// Authenticate; this is done in setup authenticator
        IdHTTPServer1.Active := False;
        Exit;
      end;

      // if we only have refresh_token or access token has expired
      // request new access_token to use with request
      OAuth2_Enhanced.RefreshAccessTokenIfRequired;

      if OAuth2_Enhanced.AccessToken.Length = 0
      then
      begin
        raise Exception.Create('Failed to authenticate properly');
        // Exit;   //need to free the stuff
      end;
    //  xoauthSASL := IdSMTP1.SASLMechanisms.Add;
    //  xoauthSASL.SASL := TIdOAuth2Bearer.Create(nil);
    //  TIdOAuth2Bearer(xoauthSASL.SASL).Token := OAuth2_Enhanced.AccessToken;
    //  TIdOAuth2Bearer(xoauthSASL.SASL).Host := IdSMTP1.Host;
    //  TIdOAuth2Bearer(xoauthSASL.SASL).Port := IdSMTP1.Port;
     // TIdOAuth2Bearer(xoauthSASL.SASL).User := clientaccount;

      try


        Url := 'https://gmail.googleapis.com/gmail/v1/users/' + emailFrom +
          '/messages/send';

        try
          HTTP := TIdHTTP.Create;
          fIdSSLIOHandlerSocketOpenSSL := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
          with fIdSSLIOHandlerSocketOpenSSL.SSLOptions do
          begin
            Method := sslvTLSv1_2;
            Mode := sslmClient;
            SSLVersions := [sslvTLSv1_2];
          end;

          HTTP.IOHandler := fIdSSLIOHandlerSocketOpenSSL;
        //  HTTP.Request.CharSet := 'utf-8';
          IdMessage := TIdMessage.Create(Application);
          MailBuilder := TIdMessageBuilderPlain.Create;
          MailBuilder.PlainText.Text := emailBody;
          MailBuilder.PlainTextCharSet := 'iso-8859-1';
        //  MailBuilder.PlainTextContentTransfer := 'base64';
          if (emailAttach <> '') and (FileExists(emailAttach))
          then
          begin
            MailBuilder.Attachments.Add(emailAttach);
            IdMessage.ContentType := 'multipart/mixed';
          end
          else
            IdMessage.ContentType := 'text/plain';

          IdMessage := MailBuilder.NewMessage();
          // if UseHTML then
          // 'text/html';
          // else
          IdMessage.ContentType := 'text/plain';

          IdMessage.Encoding := meMIME;
          IdMessage.From.Address := emailFrom;
          IdMessage.From.Name := FromName;
          IdMessage.ReplyTo.EMailAddresses := IdMessage.From.Address;
          IdMessage.Recipients.Add.Text := emailRecip;
          IdMessage.Subject := emailSubject;
          IdMessage.Body.Text := emailBody;
          IdMessage.NoEncode := False;
          MS := TStringStream.Create('', TEncoding.UTF8); // this enables me to show progress

          try
            if not Quietly
            then
            begin

              IdMessage.SaveToStream(MS);
              Sz := MS.Size;
              HTTP.onWork := EvHandler.DoWork;
              IdSMTP1.onWork := EvHandler.DoWork;
              HTTP.BeginWork(wmRead); // this enables me to show progress
            end; // if not quietly then
            with HTTP do
            begin

              Request.CustomHeaders.Add(Format('Authorization: Bearer %s',
                [OAuth2_Enhanced.AccessToken]));

              HandleRedirects := True;
              Response.KeepAlive := False;
              AllowCookies := True;
            end;

            MS.Position:=0;

            HTTP.Post(Url, MS);


            if not Quietly
            then
              ShowWait(0, 0, TimeToStr(Time) + '  email sent to ' +
                emailRecip, True);
            if not Quietly
            then
              HTTP.EndWork(wmRead);
            result := True;
          except
            On E: Exception do
            begin
              Add2Log('Error while sending email to ' + emailRecip + ': ' +
                E.Message);
              result := False;
              if not Quietly
              then
                ShowTimedMsg('Error while sending email to ' + emailRecip + ': ' +
                  E.Message, 10);
            end;
          end;

        finally
          IdSMTP1.Disconnect;
          HTTP.Free;
          // fIdSSLIOHandlerSocketOpenSSL.Free;
          MS.Free;
          IdMessage.Free;
          MailBuilder.Free;

        end;
      finally

        IdHTTPServer1.Active := False;

      end;
    end;


  7. On 11/8/2019 at 1:20 PM, Geoffrey Smith said:

    Hi @Ugochukwu Mmaduekwe,

     

    Have a look at

    https://github.com/geoffsmith82/GmailAuthSMTP/

     

    I just created a simple demo for you.  You will need to get a client_id from google in their developer toolbox.

     

    Geoffrey

    your gmailAuth on github is really good. but due to google strict requirements, I need a solution which does not use idsmtp but IDHTTP, as only have send authorization. I used your code to get the token - works brilliant. but I tried to make some code to post the message I generated using idmessage (into a tstreamstring) but always get a bad request error when posting. I think the problem is when doing IDHTTP.Post, the message is not formatted correctly. please could you advise? many thanks

×