Golang SMTP Gmail With Oauth Google
Nah dulu simple nih, cuman pake package dari sini
Oke done all is well semua berjalan sempurna. Hingga suatu waktu yang genting, ada yang mengganti email password yang dipakai buat kirim-kirim OTP tersebut, alhasil user pada complain karena tidak menerima OTP, setelah dicek lognya, ternyata ada error yang kurang lebih berbunyi:
CLIENT: 535-5.7.8 Username and Password not accepted. Learn more at535 5.7.8 https://support.google.com/mail/? p=BadCredentials 31sm5142207oto.18 - gsmtp SMTP ERROR: Password command failed: 535-5.7.8 Username and Password not accepted. Learn more at535 5.7.8 https://support.google.com/mail/?p=BadCredentials 31sm5142207oto.18 - gsmtp
Jedddder!! ibarat kesambar petir, kenapa lagi ini ya Allah 🙁. Akhirnya setelah dicari tahu akhirnya ditemukan bahwasannya google ga akan lagi support auth pake user & pass (generate app password) untuk yang baru-baru, nah yg lama-lama masih bisa dipakai dan digunakan. Kan nyebelin ya, gara-gara ganti password akhirnya kena case yg cukup baru ini haha. Untuk beritanya bisa kalian liat di blognya google sini.
Atau kalo mager buka link bisa liat sekilas di ss berikut:
Jika this announcement dibuka:
Hah Menghela nafas, merenung, chill dulu. Jadi buat teman-teman yang melihat tampilan app password di account google dari yang:
terus pas buka lagi yang baru kaya gini:
Nah kalian kemungkinan akan mengalami error diatas, meskipun sudah memakai generate password 16 digit di tampilan yang baru. Karena package tadi tidak bisa support oauth, maka kita akan sedikit config-config dan bikin sendiri.
Solusi: Memakai Oauth2 server to server Google 🍉
Secara step memang agak sedikit rumit, karena ada beberapa config yang harus dilakukan di cloud, admin, membuat utility helper untuk retrieve token JWT api google, mempelajari dokumen api service google, dan testing memakai postman atau memakai Oauth2 Playground Google.
-
Langkah pertama: Buat account_key.json dan aktifkan service api gmail
- Untuk membuat accountKey bisa dilakukan di cloud console yaa, linknya disini tinggal isi aja yg required, sisanya skip aja. Kalo bingung cari di source lain gimana cara bikin accountKey. Nah terus di tab key bikin key baru format json terus download, file json account_key ini sangat rahasia yaa jadi harap disimpan ditempat yang aman. Saat di git maupun prod kalau bisa jangan di expose, patch/taruh file key.json saat proses build saja.
- Setelah itu aktifkan service api gmail, dengan search gmail di library. Pilih gmail api dan aktifkan.
- Langkah kedua: Create Domain-wide delegation di admin
- Isi client ID dengan menyalinnya dari menu cloud console account key kolom Oauth 2 client Id
- isi Oauth scopes meggunakan: https://mail.google.com/ dan klik authorize.
- Kenapa harus menambahkan domain wide delegation? itu dilakukan agar account_key tadi memiliki otorisasi ke email service yang sudah kita aktifkan tadi. Jika tidak menambahkan authorize makan nanti akan keluar error:
oauth2: cannot fetch token: 401 Unauthorized
Response: {
"error": "unauthorized_client",
"error_description": "Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested."
}
Another source: disini
-
Langkah ketiga: Bikin library/helper untuk retrieve JWT token
- Untuk source code bisa dilihat di git saya, oiya itu pakai golang yaaa, jika kebetulan teman-teman memakai bahasa lain, bisa disesuaikan saja.
- Library ini general yaa, jadi scope nya disesuaikan dengan kebutuhan google api yg akan dipake
- Untuk token max berlaku 1 jam yaa, jadi teman-teman bisa memakai contoh strategi caching dengan time to live yaa atau mungkin bisa pakai strategi yang lain juga.
-
Langkah keempat: Bikin http request
- Hit POST dengan base url: https://gmail.googleapis.com/gmail/v1/users/me/messages/send
- Untuk header token, pake bearer yaa dengan isi token dr token yang sudah di generate library tadi.
- Untuk body diisikan sesuai format dokumen gmail api send, atau bisa disimplify seperti ini:
{
"raw": "RnJvbTogZGV2QHRoZWJlYW0uY28KVG86IHViYWlkaWxsYWhoZkBnbWFpbC5jb20KU3ViamVjdDogT1RQIE9hdXRoIFRlc3RpbmcKRGF0ZTogVGh1LCA4IE9jdCAyMDIwIDA5OjU1OjA2IC0wNjAwCk1lc3NhZ2UtSUQ6IDwxMjM0QGxvY2FsLm1hY2hpbmUuZXhhbXBsZT4KClllYWgsIGl0cyB3b3JraW5nIQ=="
}
- Untuk raw: ini diisi data yang di encode menggunakan base64, untuk isi datanya berisi kurang lebih begini:
From: from@gmail.com
To: to@gmail.com
Subject: OTP Oauth Testing
Date: Thu, 8 Oct 2023 09:55:06 -0600
Message-ID: <from@gmail.com>
Message here!
- Jika berhasil maka akan mendapat response succes:
{
"id": "18b02c5a3a3eb910",
"threadId": "18b024443a3eb660",
"labelIds": [
"SENT"
]
}
- Cek email to@gmail.com, jika berhasil maka akan masuk di kotak masuk.
- Selesai, sekian hasil dari research SMTP with Oauth. Terimakasih.
Other resource:
- https://stackoverflow.com/questions/64267579/googleapi-error-400-recipient-address-required-invalidargument
- https://www.base64encode.org/
- https://www.googlecloudcommunity.com/gc/Workspace-Developer/FAILED-PRECONDITION-Gmail-API-message-send/td-p/525880
- https://lightrun.com/answers/googleapis-google-api-nodejs-client-gmail-api-with-service-account--precondition-check-failed [Need property subject in oauth jwt]
Comments