Can't seem to get this working. Any idea why?
This is my MS configuration:
authentication
api/permissions
token configuration (empty)
"expose an api" (empty)
Code obtaining token (works fine):
new \Stevenmaguire\OAuth2\Client\Provider\Microsoft([
'clientId' => "my_id...",
'clientSecret' => "my_secret...",
'redirectUri' => "https://example.com/get/get_oauth_token.php",
'accessType' => 'offline',
// Optional (what is this doing??)
'urlAuthorize' => 'https://login.windows.net/common/oauth2/authorize',
'urlAccessToken' => 'https://login.windows.net/common/oauth2/token',
'urlResourceOwnerDetails' => 'https://outlook.office.com/api/v1.0/me'
]);
$authUrl = $provider->getAuthorizationUrl([
'scope' => ['wl.basic', 'wl.signin', 'wl.emails'] // no idea what I need here and what not - does it have to align with the app permissions?
]);
$_SESSION['oauth2state'] = $provider->getState();
header('Location: ' . $authUrl);
Using token to send mail:
$mail = new PHPMailer();
$mail->isSMTP();
$mail->Timeout = 10;
$mail->Host = "smtp.office365.com"; // smtp.office365.com, outlook.office.com, smtp-mail.outlook.com which one is it even?? Doesnt make a difference
$mail->Port = 587;
$mail->SMTPSecure = "tls";
$mail->SMTPAuth = true;
$mail->AuthType = 'XOAUTH2';
// (omitting all mail content stuff here)
$provider = new \Stevenmaguire\OAuth2\Client\Provider\Microsoft([
'clientId' => "my_id...",
'clientSecret' => "my_secret...",
'redirectUri' => "https://example.com/get/get_oauth_token.php" // is this necessary here?
]);
//Pass the OAuth provider instance to PHPMailer
$mail->setOAuth(
new OAuth([
'provider' => $provider,
'clientId' => "my_id...",
'clientSecret' => "my_secret...",
'refreshToken' => "my_refreshToken...",
// 'oauthToken' => $token, // ? are we completely ignoring the actual access token in all of this? do we ever need to update our refresh token?
'userName' => 'me#mycompany.onmicrosoft.com' // supposed to be user that gave consent?
])
);
$mail->send();
$mail->SmtpClose();
Getting this error:
2022-09-22 17:49:08 SERVER -> CLIENT: 220 FR0P281CA0070.outlook.office365.com Microsoft ESMTP MAIL Service ready at Thu, 22 Sep 2022 17:49:07 +0000
2022-09-22 17:49:08 CLIENT -> SERVER: EHLO example.com
2022-09-22 17:49:08 SERVER -> CLIENT: 250-FR0P281CA0070.outlook.office365.com Hello [85.13.129.169]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-STARTTLS250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
2022-09-22 17:49:08 CLIENT -> SERVER: STARTTLS
2022-09-22 17:49:08 SERVER -> CLIENT: 220 2.0.0 SMTP server ready
2022-09-22 17:49:08 CLIENT -> SERVER: EHLO example.com
2022-09-22 17:49:08 SERVER -> CLIENT: 250-FR0P281CA0070.outlook.office365.com Hello [85.13.129.169]250-SIZE 157286400250-PIPELINING250-DSN250-ENHANCEDSTATUSCODES250-AUTH LOGIN XOAUTH2250-8BITMIME250-BINARYMIME250-CHUNKING250 SMTPUTF8
Bad Request
/www/htdocs/w014af32/me/vendor/stevenmaguire/oauth2-microsoft/src/Provider/Microsoft.php(79)
#0 /www/htdocs/w014af32/me/vendor/league/oauth2-client/src/Provider/AbstractProvider.php(628): Stevenmaguire\OAuth2\Client\Provider\Microsoft->checkResponse(Object(GuzzleHttp\Psr7\Response), Array)
#1 /www/htdocs/w014af32/me/vendor/league/oauth2-client/src/Provider/AbstractProvider.php(537): League\OAuth2\Client\Provider\AbstractProvider->getParsedResponse(Object(GuzzleHttp\Psr7\Request))
#2 /www/htdocs/w014af32/me/vendor/phpmailer/phpmailer/src/OAuth.php(115): League\OAuth2\Client\Provider\AbstractProvider->getAccessToken(Object(League\OAuth2\Client\Grant\RefreshToken), Array)
#3 /www/htdocs/w014af32/me/vendor/phpmailer/phpmailer/src/OAuth.php(128): PHPMailer\PHPMailer\OAuth->getToken()
#4 /www/htdocs/w014af32/me/vendor/phpmailer/phpmailer/src/SMTP.php(598): PHPMailer\PHPMailer\OAuth->getOauth64()
#5 /www/htdocs/w014af32/me/vendor/phpmailer/phpmailer/src/PHPMailer.php(2190): PHPMailer\PHPMailer\SMTP->authenticate('', '', 'XOAUTH2', Object(PHPMailer\PHPMailer\OAuth))
#6 /www/htdocs/w014af32/me/vendor/phpmailer/phpmailer/src/PHPMailer.php(2003): PHPMailer\PHPMailer\PHPMailer->smtpConnect(Array)
#7 /www/htdocs/w014af32/me/vendor/phpmailer/phpmailer/src/PHPMailer.php(1662): PHPMailer\PHPMailer\PHPMailer->smtpSend('Date: Thu, 22 S...', 'test content\r\n')
#8 /www/htdocs/w014af32/me/vendor/phpmailer/phpmailer/src/PHPMailer.php(1500): PHPMailer\PHPMailer\PHPMailer->postSend()
#9 /www/htdocs/w014af32/me/includes/helpers/mail.php(182): PHPMailer\PHPMailer\PHPMailer->send()
#10 /www/htdocs/w014af32/me/includes/helpers/mail.php(113): mailSendSingle(Object(PHPMailer\PHPMailer\PHPMailer), Array, true)
#11 /www/htdocs/w014af32/me/get/test4.php(25): mailSend(Array)
#12 {main}
# Args:
checkResponse: [{},{"error":"invalid_client","error_description":"The client does not exist or is not enabled for consumers. If you are the application developer, configure a new application through the App Registrations in the Azure Portal at https:\/\/go.microsoft.com\/fwlink\/?linkid=2083908.","correlation_id":"4dc377bd-0d5d-4444-bdd4-82b862f86177"}]
getParsedResponse: [{}]
getAccessToken: [{},{"refresh_token":"my refreshToken..."}]
authenticate: ["","","XOAUTH2",{}]
smtpConnect: [{"ssl":{"verify_peer":false,"verify_peer_name":false,"allow_self_signed":true}}]
smtpSend: ["Date: Thu, 22 Sep 2022 19:49:08 +0200\r\nTo: John Doe <me#example.com>\r\nFrom: John Doe <me#mycompany.onmicrosoft.com>\r\nReply-To: John Doe <me#mycompany.onmicrosoft.com>\r\nSubject: test mail\r\nMessage-ID: <AAtH5DrcPQ9Fn4PysOdjIt0OnDbByC4eaRYVnJh33M#example.com>\r\nX-Mailer: PHPMailer 6.6.4 (https:\/\/github.com\/PHPMailer\/PHPMailer)\r\nMIME-Version: 1.0\r\nContent-Type: text\/html; charset=utf-8\r\n\r\n","test content\r\n"]
mailSendSingle: [{"Priority":null,"CharSet":"utf-8","ContentType":"text\/html","Encoding":"7bit","ErrorInfo":"","From":"me#mycompany.onmicrosoft.com","FromName":"John Doe","Sender":"me#mycompany.onmicrosoft.com","Subject":"test mail","Body":"test content","AltBody":"","Ical":"","WordWrap":0,"Mailer":"smtp","Sendmail":"\/usr\/sbin\/sendmail","UseSendmailOptions":true,"ConfirmReadingTo":"","Hostname":"","MessageID":"","MessageDate":"","Host":"smtp.office365.com","Port":"587","Helo":"","SMTPSecure":"tls","SMTPAutoTLS":true,"SMTPAuth":true,"SMTPOptions":{"ssl":{"verify_peer":false,"verify_peer_name":false,"allow_self_signed":true}},"Username":"","Password":"","AuthType":"XOAUTH2","Timeout":10,"dsn":"","SMTPDebug":2,"Debugoutput":"html","SMTPKeepAlive":false,"SingleTo":false,"do_verp":false,"AllowEmpty":false,"DKIM_selector":"","DKIM_identity":"","DKIM_passphrase":"","DKIM_domain":"","DKIM_copyHeaderFields":true,"DKIM_extraHeaders":[],"DKIM_private":"","DKIM_private_string":"","action_function":"","XMailer":""},{"from_mail":"me#mycompany.onmicrosoft.com","from_name":"John Doe","smtp_profile":3,"from_user":1,"to_mail":"me#example.com","to_name":"John Doe","to_type":"staff","to_id":3,"template":0,"debug":true,"testing":true,"subject":"test mail","type":"test","date":"2022-09-22 19:49:08","content":"test content","reply_to":"me#mycompany.onmicrosoft.com"},true]
mailSend: [{"from_mail":"me#mycompany.onmicrosoft.com","from_name":"John Doe","smtp_profile":3,"from_user":1,"to_mail":"me#example.com","to_name":"John Doe","to_type":"staff","to_id":3,"template":0,"debug":true,"testing":true,"subject":"test mail","type":"test","date":"2022-09-22 19:49:08","content":"test content","reply_to":"me#mycompany.onmicrosoft.com"}]
2022-09-22 17:49:08 CLIENT -> SERVER: QUIT
2022-09-22 17:49:08 SERVER -> CLIENT: 221 2.0.0 Service closing transmission channel
I know it's a lot of code but there isn't really much to say, I could ommit the whole token obtaining because it works. I assume the error lies somewhere in the azure configuration? The user I've obtained the token with is just a "member" (Role "Global administrator"), the "owner" of the app is another one.
using these options for the provider (in both places, aquiring token and sending mail) did it (it's the tenant id):
'urlAuthorize' => 'https://login.microsoftonline.com/b3095h58-5987-4489-a1dd-b132f2f38113/oauth2/authorize',
'urlAccessToken' => 'https://login.microsoftonline.com/b3095h58-5987-4489-a1dd-b132f2f38113/oauth2/token'
It seemed irrelevant whether to use windows.net or microsoftonline.com
However now I'm at the same point as described here. Funnily even using Thunderbird to test the oauth authentification fails for sending (receiving is fine though).
I'm trying to send emails from a rails application using smtp. Sending the emails does not cause problems, but some recipients do not receive the emails. Instead, delivery notices ("Undelivered Mail Returned to Sender") are returned with:
Diagnostic-Code: smtp; 554 5.7.0 Reject, id=04635-09 - spam: This message was
blocked for security reasons
Now the strange part:
Sending a test mail through a mail client via smtp (TLS/SSL true, port 465, auth: password) works. The recipient receives the email without error.
Sending the email via sendemail -o tls=yes -f foo#fiedlschuster.de -t bar#example.com -s 212-227-10-158.benjaminkant.de -xu foo#fiedlschuster.de -xp password -u "Hello from sendemail" -m "This is a test." -vvvv works. The recipient receives the email without error.
Sending the email through the mail gem (which is what I want to achieve) using the same smtp account works, but the recipient does not receive the email. Instead, "Undelivered Mail Returned to Sender" is sent to the sender address.
require 'mail'
options = {address: "212-227-10-158.benjaminkant.de", user_name: "foo#fiedlschuster.de",
password: "...", authentication: "login"}
Mail.defaults { delivery_method :smtp, options }
message = Mail.new(to: "bar#example.com", from: "foo#fiedlschuster.de",
subject: "Test", body: "This is a test.")
message.deliver
Also, I've tried these options, resulting in the same issue:
options = {address: "212-227-10-158.benjaminkant.de", user_name: "foo#fiedlschuster.de",
password: "...", authentication: "login"}
options = {address: "212-227-10-158.benjaminkant.de", user_name: "foo#fiedlschuster.de",
password: "...", authentication: "login",
enable_starttls_auto: true}
options = {address: "212-227-10-158.benjaminkant.de", user_name: "foo#fiedlschuster.de",
password: "...", authentication: "login",
port: 465, enable_starttls_auto: false, ssl: true}
options = {address: "212-227-10-158.benjaminkant.de", user_name: "foo#fiedlschuster.de",
password: "..."}
Does this make sense to anyone?
Additional information
MX records
▶ host -t MX fiedlschuster.de
fiedlschuster.de mail is handled by 10 mail.fiedlschuster.de.
▶ host -t MX 212-227-10-158.benjaminkant.de
212-227-10-158.benjaminkant.de has no MX record
Firstly, it's worth checking message.to_s
Date: Wed, 24 Jul 2019 17:15:08 +0100
From: foo#fiedlschuster.de
To: bar#example.com
Message-ID: <5d38840ce52e9_5a6a2af20734c5b418642#my-machine-name.mail>
Subject: Test
Mime-Version: 1.0
Content-Type: text/plain;
charset=UTF-8
Content-Transfer-Encoding: 7bit
This is a test.
The only thing that screams out at me is the Message-ID - it uses your machine name. It's possible that some spam filters compare this to the sender's domain name, and if they don't match, assume that you are a bot?
(I don't know what sendemail does here, but my Thunderbird certainly uses my domain name)
So I'd try:
message = Mail.new(to: "bar#example.com", from: "foo#fiedlschuster.de",
subject: "Test", body: "This is a test.", message_id: "#{Mail.random_tag}#fiedlschuster.de")
I've been following the Laravel Mail docs https://laravel.com/docs/5.4/mail to send email via a SparkPost account. When I try and send I'm getting
ClientException
Client error: `POST https://api.sparkpost.com/api/v1/transmissions` resulted in a `401 Unauthorized` response:
{"errors": [ {"message": "Unauthorized."} ]}
As per the docs I've got the sparkpost key in config/services.php and though the docs don't mention anything about it (why not!?) a bit of Googling convinced me to set the mail driver etc. in my .env file. I then have a web route to check the config being used,
Route::get('test', function()
{
dd(Config::get('mail'));
});
which gives
array:9 [▼
"driver" => "sparkpost"
"host" => "smtp.sparkpostmail.com"
"port" => "587"
"from" => array:2 [▶]
"encryption" => "tls"
"username" => "my-sparkpost-account-login-email-address"
"password" => "my-sparkpost-account-login-password"
"sendmail" => "/usr/sbin/sendmail -bs"
"markdown" => array:2 [▶]
]
I actually want to use a mailable and views which I've set up, but just to test the sending I bypassed these and set the following route to test:
Route::get('/sparkpost', function () {
Mail::send('emails.test', [], function ($message) {
$message
->from('marketing#my-sparkpost-sending-domain.com', 'Me')
->to('my-email-address', 'My-Name')
->subject('A Test Email');
});
});
which got the error at the top (testing with my mailables and views gave the exact same error which makes me think they are correctly set up - assuming the above test route is correct).
The on thing I'm wondering about is I'm testing on my local machine, so test URL is http://localhost/seg/public/sparkpost - I'm wondering if this is tripping SparkPost up (i.e. do I have to actually be sending from a server running at the same domain as the sending domain configured in sparkpost, or is it just the sending address in the email that has to match?)
Thanks for any suggestions!
if you use smtp driver,
You need go to Account > SMTP Relay to get credentials for SMTP,
it's not your sparkpost account credentials.
if you use sparkpost driver,
you need put api key of sparkpost into config/services.php, there is no need to input smtp username and password if you use sparkpost driver
I testing Email Migration API V2 with google client api for ruby version 0.7.1
For multipart upload I always getting this response from server:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "backendError",
"message": "Backend Error"
}
],
"code": 503,
"message": "Backend Error"
}
}
Here is my code:
client = Google::APIClient.new(
:application_name => 'My app',
:application_version => '1.1.0'
)
#auth code skipped
migration = client.discovered_api('admin', 'email_migration_v2')
file = {"isInbox" => true}
mail = StringIO.new "Date: Wed, 03 Jan 2013 02:56:03 -0800
From: admin#example.org
To: liz#example.com
Subject: Hello World!
MIME-Version: 1.0
Content-Type: text/html; charset=windows-1252
Content-transfer-encoding: 8bit
And I think to myself... What a wonderful world!"
media = Google::APIClient::UploadIO.new(mail, 'message/rfc822')
client.execute!(:api_method=> migration.mail.insert,
:media => media,
:body_object => file,
parameters: {
'userKey' => "name#domain.com",
'uploadType' => 'multipart',
})
Some logs info
DEBUG 18:58:13 rails [pid=6311]: Google::APIClient::Request Sending API request post https://www.googleapis.com/upload/email/v2/users/name#domain.com/mail?uploadType=multipart {"User-Agent"=>"My app/1.1.0 google-api-ruby-client/0.7.1 Mac OS X/10.9.4\n (gzip)", "Content-Type"=>"multipart/related;boundary=-----------RubyApiMultipartPost", "Content-Length"=>"682", "Accept-Encoding"=>"gzip", "Authorization"=>"Bearer xxxxx", "Cache-Control"=>"no-store"}
POST BODY:
DEBUG 18:58:13 rails [pid=6311]: -------------RubyApiMultipartPost
Content-Disposition: form-data; name=""; filename="file.json"
Content-Length: 16
Content-Type: application/json
Content-Transfer-Encoding: binary
{"isInbox":true}
-------------RubyApiMultipartPost
Content-Disposition: form-data; name=""; filename="local.path"
Content-Length: 249
Content-Type: message/rfc822
Content-Transfer-Encoding: binary
Date: Wed, 03 Jan 2013 02:56:03 -0800
From: admin#example.org
To: liz#example.com
Subject: Hello World!
MIME-Version: 1.0
Content-Type: text/html; charset=windows-1252
Content-transfer-encoding: 8bit
And I think to myself... What a wonderful world!
-------------RubyApiMultipartPost--
Please help me understand why google responds with 503. And how I can resolve it.
I am sure that I didn't reach API quota.
Update 1:
Looks like Content-Disposition header is the reason of 503 error, Because without it upload works fine!
I've spent the past couple of days trying to access Google's Directory API in Ruby but haven't been able to get it working. According to this document the Directory API can be authorized using 2lo:
If your application has certain unusual authorization requirements, such as logging in at the same time as requesting data access (hybrid) or domain-wide delegation of authority (2LO), then you cannot currently use OAuth 2.0 tokens. In such cases, you must instead use OAuth 1.0 tokens and an API key. You can find your application's API key in the Google APIs Console, in the Simple API Access section of the API Access pane.
I currently have working code that can access the Provisioning API using 2lo. From the documentation it sounds that I can use this same code to access the Directory API by just adding an API access key parameter to the request and enabling a few permissions. However, it's not working and I have no idea why.
Here is the request code:
def self.get_user2(email)
#client = Google::APIClient.new(:authorization => :two_legged_oauth_1)
#client.authorization.client_credential_key = GOOGLE_APP_KEY
#client.authorization.client_credential_secret = GOOGLE_APP_SECRET
#directory = #client.discovered_api('admin', 'directory_v1')
result = #client.execute(
#directory.users.get,
'userKey' => email,
:key => GOOGLE_API_KEY
)
JSON.parse(result.body)
end
This gets me the response:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
I've added the required scope to my manifest file,
<Scope id="usersAPI">
<Url>https://www.googleapis.com/auth/admin.directory.user.readonly</Url>
<Reason>See all users in your company.</Reason>
</Scope>
and also enabled the Admin SDK for my project in the API console.
Here is the log output after adding Faraday.default_connection.response :logger to my development.rb file:
get https://www.googleapis.com/admin/directory/v1/users/brian#crushing.mygbiz.com?key=AIzaSyAHYBWlC_qiihRtTKTZleZlAw2ts8Q1WO8
User-Agent: "google-api-ruby-client/0.6.4 Mac OS X/10.8.4"
Authorization: "OAuth oauth_consumer_key=\"76548528623.apps.googleusercontent.com\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"1375899810\", oauth_nonce=\"de4d976eed6883a06b3f6084e3dd0db4\", oauth_version=\"1.0\", oauth_signature=\"3D7aqhBeaCYOYyaF8bWpaM9MA8U%3D\""
Cache-Control: "no-store"
Content-Type: "application/x-www-form-urlencoded"
401
www-authenticate: "AuthSub realm=\"https://www.google.com/accounts/AuthSubRequest\""
content-type: "application/json; charset=UTF-8"
date: "Wed, 07 Aug 2013 18:23:30 GMT"
expires: "Wed, 07 Aug 2013 18:23:30 GMT"
cache-control: "private, max-age=0"
x-content-type-options: "nosniff"
x-frame-options: "SAMEORIGIN"
x-xss-protection: "1; mode=block"
server: "GSE"
connection: "close"
After searching the internet for the past day I am out of ideas for why this isn't working. Ideas anyone?
It turns out I was missing the 'xoauth_requestor_id' field. Thanks to sqrrrl for answering my question on github