Django and Mailgun : 552 sorry, your envelope sender domain must exist (#5.7.1) - django

I'm trying to send mail using Django and Mailgun through the Anymail package and with an OVH server.
I'm currently receiving the 552 sorry, your envelope sender domain must exist (#5.7.1) error.
In this question/answer, it is suggested that I would need a "from" header, but the response I'm getting seems to show that the header is already included :
"headers": {
"to": "evenements#mydomain-longversion.org",
"message-id": "20160915065953.15168.46300.4ABD80EB#mailgun.mydomain.fr",
"from": "covoiturage#mydomain.fr",
"subject": "Mail test !"
},
Here is the full response, for reference :
{
"severity": "permanent",
"tags": [],
"storage": {
"url": "https://si.api.mailgun.net/v3/domains/mailgun.mydomain.fr/messages/eyJwIjpmYWxzZSwiayI6ImI5OGIyN2QzLTM2MmEtNGJjNi05ZWViLTRlMTA0NTVmYTIxMiIsInMiOiJlNmY5NzZhZTYwIiwiYyI6InNiaWFkIn0=",
"key": "eyJwIjpmYWxzZSwiayI6ImI5OGIyN2QzLTM2MmEtNGJjNi05ZWViLTRlMTA0NTVmYTIxMiIsInMiOiJlNmY5NzZhZTYwIiwiYyI6InNiaWFkIn0="
},
"delivery-status": {
"tls": false,
"mx-host": "redirect.ovh.net",
"attempt-no": 1,
"description": null,
"session-seconds": 0.9216420650482178,
"code": 552,
"message": "552 sorry, your envelope sender domain must exist (#5.7.1)",
"certificate-verified": false
},
"recipient-domain": "mydomain-longversion.org",
"event": "failed",
"campaigns": [],
"reason": "generic",
"user-variables": {},
"flags": {
"is-routed": null,
"is-authenticated": true,
"is-system-test": false,
"is-test-mode": false
},
"log-level": "error",
"timestamp": 1473922798.282194,
"envelope": {
"transport": "smtp",
"sender": "postmaster#mailgun.mydomain.fr",
"sending-ip": "209.61.151.224",
"targets": "evenements#mydomain-longversion.org"
},
"message": {
"headers": {
"to": "evenements#mydomain-longversion.org",
"message-id": "20160915065953.15168.46300.4ABD80EB#mailgun.mydomain.fr",
"from": "covoiturage#mydomain.fr",
"subject": "Mail test !"
},
"attachments": [],
"recipients": [
"evenements#mydomain-longversion.org"
],
"size": 643
},
"recipient": "evenements#mydomain-longversion.org",
"id": "TfJKwpoZQq6bM-MW5sm6nA"
}
And here is my Django code :
def SendTestEmail(request):
if request.user.is_staff and settings.DEBUG == True :
send_mail(
subject='Mail test !',
message='''Bonjour {}, votre email a bien été envoyé.'''.format(request.user.get_full_name()),
recipient_list=['evenements#mydomain-longversion.org',],
from_email=settings.DEFAULT_FROM_EMAIL,
fail_silently=False,
)
messages.success(request, 'Email correctement envoyé !')
return redirect('rideshare_event_list')

Try using covoiturage#mailgun.mydomain.fr as your from address instead of covoiturage#mydomain.fr.
I'm afraid I'm not sure whether it's possible to use covoiturage#mydomain.fr as the from address.

Related

PayPal API integration with Django

I am integrating PayPal API with Django back-end (Reactcjs for front-end) in my project with the help of sandbox accounts (#business & #personal account). What I did till now is I have a client_id and a secret used for generating access_token from paypal.
import requests
import base64
def PaypalToken(client_ID, client_Secret):
url = "https://api.sandbox.paypal.com/v1/oauth2/token"
data = {
"client_id":client_ID,
"client_secret":client_Secret,
"grant_type":"client_credentials"
}
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic {0}".format(base64.b64encode((client_ID + ":" + client_Secret).encode()).decode())
}
token = requests.post(url, data, headers=headers)
return token
x = PaypalToken(my_client_ID, my_client_Secret)
print(x.text)
<code>
This gonna provide me a token then I use that token to post json object on paypal.
<pre>
headers = {"Content-Type": "application/json", "Authorization": 'Bearer' + token}
url = https://api.sandbox.paypal.com/v2/checkout/orders
data = '{
"intent": "CAPTURE",
"application_context": {
"return_url": "https://www.example.com",
"cancel_url": "https://www.example.com",
"brand_name": "EXAMPLE INC",
"landing_page": "BILLING",
"shipping_preference": "SET_PROVIDED_ADDRESS",
"user_action": "CONTINUE"
},
"purchase_units": [
{
"reference_id": "PUHF",
"description": "Sporting Goods",
"custom_id": "CUST-HighFashions",
"soft_descriptor": "HighFashions",
"amount": {
"currency_code": "USD",
"value": "220.00",
"breakdown": {
"item_total": {
"currency_code": "USD",
"value": "180.00"
},
"shipping": {
"currency_code": "USD",
"value": "20.00"
},
"handling": {
"currency_code": "USD",
"value": "10.00"
},
"tax_total": {
"currency_code": "USD",
"value": "20.00"
},
"shipping_discount": {
"currency_code": "USD",
"value": "10"
}
}
},
"items": [
{
"name": "T-Shirt",
"description": "Green XL",
"sku": "sku01",
"unit_amount": {
"currency_code": "USD",
"value": "90.00"
},
"tax": {
"currency_code": "USD",
"value": "10.00"
},
"quantity": "1",
"category": "PHYSICAL_GOODS"
},
{
"name": "Shoes",
"description": "Running, Size 10.5",
"sku": "sku02",
"unit_amount": {
"currency_code": "USD",
"value": "45.00"
},
"tax": {
"currency_code": "USD",
"value": "5.00"
},
"quantity": "2",
"category": "PHYSICAL_GOODS"
}
],
"shipping": {
"method": "United States Postal Service",
"name": {`enter code here`
"full_name":"John Doe"
},
"address": {
"address_line_1": "123 Townsend St",
"address_line_2": "Floor 6",
"admin_area_2": "San Francisco",
"admin_area_1": "CA",
"postal_code": "94107",
"country_code": "US"
}
}
}
]
}'
result = requests.post(url, data, headers=header)
<code>
this gonna give me 4 links
<pre>
{
"id": "5O190127TN364715T",
"status": "CREATED",
"links": [
{
"href": "https://api.paypal.com/v2/checkout/orders/5O190127TN364715T",
"rel": "self",
"method": "GET"
},
{
"href": "https://www.paypal.com/checkoutnow?token=5O190127TN364715T",
"rel": "approve",
"method": "GET"
},
{
"href": "https://api.paypal.com/v2/checkout/orders/5O190127TN364715T/capture",
"rel": "capture",
"method": "POST"
}
]
}
<code>
What Next ?
First, implement two routes that return only JSON data. One for creating the order and one for capturing it after approval.
For the interim payer approval step, ignore those 4 links which are for old integration patterns that redirect away from your site. In place of that, use the PayPal JS SDK for in-context approval (keeping your site loaded in the background) and have it fetch from those two routes on your server.
Here's the approval flow in pure JS: https://developer.paypal.com/demo/checkout/#/pattern/server
For the same with react, see #paypal/react-papal-js and its storybook examples.

Google action request for grant_type=refresh_token does not update conversation object with new access token

I'm developing a google action which is configured for account linking using Linking Type: "OAuth" / "Authorization code". The OAuth2 authorization server functions are hosted in the same place as the linked business application server, so I have full visibility of the traffic in both regards.
The initial linking process works perfectly every time; however, a problem arises when the original access token expires, and a new one is requested grant_type=refresh_token. Included below are the sanitized log contents from our server's execution logic generated by invocation of the google action using Actions Console "Test" simulator, after the original access token has expired. As expected, the google action first requests a new access token by calling the Token Url with grant_type=refresh_token. Our server then returns content to the caller
shown below under SmartAssistOAuthToken: result= as
{"expires_in":600,"token_type":"Bearer","access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.5XRFvkrBr7PCfyyqSMW1nNJBI0EceQgFrMA-6I04sQA"}
Having received the new token, the Google action proceeds to the main intent / webhook handler which contains a REST request back to the same server to retrieve some information about the current user's account.
This is shown below as: >****> 2021/07/15 12:16:18 (-05:00) - /cgi-bin/w2w.dll/sa_anon?cmd=login...
>********> 2021/07/15 12:16:15 (-05:00) - /cgi-bin/w2w.dll/AoG_token?
----------------------------------------------------------------------------------------------------
SmartAssistOAuthToken: contentfields=
grant_type=refresh_token
refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.65URfGpCL4s9nZiUc2pvYRZydK6jKanI5DZAZm04BtM
client_id=xxxx
client_secret=xxxx
----------------------------------------------------------------------------------------------------
SmartAssistOAuthToken: result= (...using 600 to speed things up a bit)
{"expires_in":600,"token_type":"Bearer","access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.5XRFvkrBr7PCfyyqSMW1nNJBI0EceQgFrMA-6I04sQA"}
----------------------------------------------------------------------------------------------------
>********> 2021/07/15 12:16:18 (-05:00) - /cgi-bin/w2w.dll/sa_anon?cmd=login&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.FfUGlS71IaIU3LdkiJtUKfBBZwjSaN5D0s1ECpzxop4
----------------------------------------------------------------------------------------------------
SmartAssistLogin: QueryFields=
cmd=login
access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.FfUGlS71IaIU3LdkiJtUKfBBZwjSaN5D0s1ECpzxop4
----------------------------------------------------------------------------------------------------
ValidAccessTokenInfo: AccessToken's JWT has expired.
----------------------------------------------------------------------------------------------------
SmartAssistError: Error={"error_uri":"https:xxxx","error_description":"Invalid authorization credential.","error":"invalid_request"}
At the end of the "login" REST request is the access token which I read from conv.session.params.bearerToken, and then add to the url.
/cgi-bin/w2w.dll/sa_anon?cmd=login&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.FfUGlS71IaIU3LdkiJtUKfBBZwjSaN5D0s1ECpzxop4
However, the value provided by conv.session.params.bearerToken (eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.FfUGlS71IaIU3LdkiJtUKfBBZwjSaN5D0s1ECpzxop4) is not the new one returned to the refresh token request (eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.5XRFvkrBr7PCfyyqSMW1nNJBI0EceQgFrMA-6I04sQA). As such, my server returns an error for the request because the original token is no longer valid / expired.
The entire (sanitized) incoming conv object is as follows, wherein all references to bearerToken are the same recently expired token:
{
"overwrite": false,
"digested": false,
"request": {
"handler": {
"name": "main"
},
"intent": {
"name": "actions.intent.MAIN",
"params": {},
"query": "Talk to work assistant"
},
"scene": {
"name": "Main",
"slotFillingStatus": "UNSPECIFIED",
"slots": {}
},
"session": {
"id": "ABwppHFsSDza7b0R74-kOOBCudqHWhrjIMma8mnaLjTDFg55O68MIjBIPRgaSEyAH31RPOJGG9VhrIl283LWY6xXZsw",
"params": {},
"typeOverrides": [],
"languageCode": ""
},
"user": {
"locale": "en-US",
"params": {
"AccountLinkingSlot": "LINKED",
"bearerToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.FfUGlS71IaIU3LdkiJtUKfBBZwjSaN5D0s1ECpzxop4",
},
"accountLinkingStatus": "LINKED",
"verificationStatus": "VERIFIED",
"packageEntitlements": [],
"gaiamint": "",
"permissions": [],
"lastSeenTime": "2021-07-15T16:15:48Z"
},
"home": {
"params": {}
},
"device": {
"capabilities": ["SPEECH", "RICH_RESPONSE", "LONG_FORM_AUDIO"],
"timeZone": {
"id": "America/Chicago",
"version": ""
}
}
},
"headers": {
"host": "us-central1-work-assistant-b9910.cloudfunctions.net",
"user-agent": "Google-ActionsOnGoogle/1.0",
"transfer-encoding": "chunked",
"accept-encoding": "gzip, deflate, br",
"content-type": "application/json;charset=UTF-8",
"forwarded": "for=\"66.249.83.57\";proto=https",
"function-execution-id": "zn46t5q3mkfr",
"google-actions-api-version": "3",
"google-assistant-signature": "xxxx",
"traceparent": "00-6b5c4d0aa670f39009910ec1f7e908ee-2abd7ee7886b286d-00",
"x-appengine-country": "ZZ",
"x-appengine-default-version-hostname": "d1c092144ed53556ap-tp.appspot.com",
"x-appengine-https": "on",
"x-appengine-request-log-id": "60f06d6200ff0c6741e353b4fb0001737e6431633039323134346564353335353661702d7470000133343061346661353033613135323331626363326539303833646463386639313a310001010c",
"x-appengine-timeout-ms": "599998",
"x-appengine-user-ip": "66.249.83.57",
"x-cloud-trace-context": "6b5c4d0aa670f39009910ec1f7e908ee/3079757253082556525",
"x-forwarded-for": "66.249.83.57",
"x-forwarded-proto": "https",
"connection": "close"
},
"handler": {
"name": "main"
},
"intent": {
"name": "actions.intent.MAIN",
"query": "Talk to work assistant",
"params": {}
},
"scene": {
"name": "Main",
"slotFillingStatus": "UNSPECIFIED",
"slots": {},
"next": {}
},
"session": {
"id": "ABwppHFsSDza7b0R74-kOOBCudqHWhrjIMma8mnaLjTDFg55O68MIjBIPRgaSEyAH31RPOJGG9VhrIl283LWY6xXZsw",
"params": {
"AccountLinkingSlot": "LINKED",
"bearerToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.FfUGlS71IaIU3LdkiJtUKfBBZwjSaN5D0s1ECpzxop4",
},
"typeOverrides": [],
"languageCode": ""
},
"user": {
"locale": "en-US",
"params": {
"AccountLinkingSlot": "LINKED",
"bearerToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.FfUGlS71IaIU3LdkiJtUKfBBZwjSaN5D0s1ECpzxop4",
},
"accountLinkingStatus": "LINKED",
"verificationStatus": "VERIFIED",
"packageEntitlements": [],
"gaiamint": "",
"permissions": [],
"lastSeenTime": "2021-07-15T16:15:48Z"
},
"device": {
"capabilities": ["SPEECH", "RICH_RESPONSE", "LONG_FORM_AUDIO"],
"currentLocation": {},
"timeZone": {
"id": "America/Chicago",
"version": ""
}
},
"home": {
"params": {}
},
"expected": {},
"context": {},
"prompt": {
"override": false
},
"_internal": {
"promptSet": false,
"orig": {
"scene": {
"name": "Main",
"slotFillingStatus": "UNSPECIFIED",
"slots": {},
"next": {}
},
"session": {
"id": "ABwppHFsSDza7b0R74-kOOBCudqHWhrjIMma8mnaLjTDFg55O68MIjBIPRgaSEyAH31RPOJGG9VhrIl283LWY6xXZsw",
"params": {},
"typeOverrides": [],
"languageCode": ""
},
"user": {
"locale": "en-US",
"params": {
"AccountLinkingSlot": "LINKED",
"bearerToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxx.FfUGlS71IaIU3LdkiJtUKfBBZwjSaN5D0s1ECpzxop4",
},
"accountLinkingStatus": "LINKED",
"verificationStatus": "VERIFIED",
"packageEntitlements": [],
"gaiamint": "",
"permissions": [],
"lastSeenTime": "2021-07-15T16:15:48Z"
},
"home": {
"params": {}
}
}
}
}
The relevant google action webhook code looks something like this:
const {conversation,
Suggestion,
Simple,
Card,
Image
} = require('#assistant/conversation');
const functions = require('firebase-functions');
const app = conversation();
...
const getAccessToken = (conv) => {
return conv.session.params.bearerToken;
};
...
app.handle('main', async conv => {
...
console.log("main: >>>>>>>>>>>>>> conv=",JSON.stringify(conv));
...
if (conv.user.verificationStatus !== 'VERIFIED') {
conv.add('Sorry, your account is not verified yet so you cannot be here.');
return;
}
...
await getRemoteData(`${getFullredirectpath()}sa_anon?cmd=login&access_token=${getAccessToken(conv)}`)
.then((response) => {
(success handling...)
})
.catch((err) => {
(Error handling...)
return;
});
...
}
This problem doesn't happen every time a token is refreshed, but it does happen frequently, and seemingly more so, the longer the time between sessions. I can almost always count on it to happen overnight.

SSRS Subscription using REST API

Can we create/modify SSRS Subscription using REST API as SQL Server Reporting services 2017 supports REST API calls?
here is an online swagger example they built, but some properties are invalid or missing. Ex: Schedule property is missing and ExtensionSettings.ParameterValues is an array instead of an object
https://app.swaggerhub.com/apis/microsoft-rs/SSRS/2.0#/Subscriptions/GetSubscriptions
here is an example of a body message that works for me when posting:
{ "DataQuery": null, "DeliveryExtension": "Report Server Email", "Description": "test3", "EventType": "TimedSubscription", "ExtensionSettings": { "Extension": "Report Server Email", "ParameterValues": [ { "IsValueFieldReference": false, "Name": "TO", "Value": "userName" }, { "IsValueFieldReference": false, "Name": "IncludeReport", "Value": "True" }, { "IsValueFieldReference": false, "Name": "RenderFormat", "Value": "PDF" }, { "IsValueFieldReference": false, "Name": "Subject", "Value": "#ReportName was executed at #ExecutionTime" }, { "IsValueFieldReference": false, "Name": "IncludeLink", "Value": "True" }, { "IsValueFieldReference": false, "Name": "Priority", "Value": "NORMAL" } ] }, "IsActive": true, "IsDataDriven": false, "LastRunTime": null, "LastStatus": "New Subscription", "LocalizedDeliveryExtensionName": "E-Mail", "ModifiedBy": "userName", "ModifiedDate": "2020-09-04T13:45:51.343-05:00", "Owner": "userName", "ParameterValues": [], "Report": "/Folder Name/Report Name", "Schedule": { "Definition": { "EndDate": "0001-01-01T00:00:00Z", "EndDateSpecified": false, "Recurrence": { "DailyRecurrence": { "DaysInterval": 1 }, "MinuteRecurrence": null, "MonthlyDOWRecurrence": null, "MonthlyRecurrence": null, "WeeklyRecurrence": null }, "StartDateTime": "2020-09-04T02:00:00-05:00" }, "ScheduleID": null }, "ScheduleDescription": "At 2:00 AM every day, starting 9/4/2020" }

How to send a request?

I need to send a request with the following data
"order": {
"server_callback_url": "http://site.id/callback",
"currency": "UAH",
"amount": "1400",
"order_type": "settlement",
"response_url": "http://site.id/test/responsepage/",
"order_id": "test1234561467462099.19",
"operation_id": "test1234561467462099.19",
"order_desc": "test order",
"merchant_id": 700001,
"receiver": [
{
"requisites": {
"amount": 100,
"merchant_id": 500001
},
"type": "merchant"
},{
"requisites": {
"amount": 200,
"merchant_id": 600001
},
"type": "merchant"
},
]
}
I need to send them to https://api.fondy.eu/api/settlement
But I never did that. I am not familiar with DRF at all. Tell me how to implement it, please.
If we visit the endpoint, it says that only POST methods are allowed. We can make a POST request for example with the requests package.
import requests
data = {
"order": {
"server_callback_url": "http://site.id/callback",
"currency": "UAH",
"amount": "1400",
"order_type": "settlement",
"response_url": "http://site.id/test/responsepage/",
"order_id": "test1234561467462099.19",
"operation_id": "test1234561467462099.19",
"order_desc": "test order",
"merchant_id": 700001,
"receiver": [
{
"requisites": {
"amount": 100,
"merchant_id": 500001
},
"type": "merchant"
},{
"requisites": {
"amount": 200,
"merchant_id": 600001
},
"type": "merchant"
},
]
}
}
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
response = requests.post('https://api.fondy.eu/api/settlement', data=data, headers=headers)
The header can be important, since it tells you in what format you make your reqest, and some APIs do not work if you do not set the Content-type properly.
The response is here a Response object, and you can parse the response to a Python dictionary with:
response.json()
locally this gives me:
{'response': {'error_code': 1002,
'error_message': 'Application error',
'request_id': 'iUxQzJfyBuxdI'}}
The status code is 200, so that probably means that the callback you specified was not valid (or some other items in your request).
You could use DRF as the documentation :
https://www.django-rest-framework.org/tutorial/2-requests-and-responses/
Or without DRF :
# importing the requests library
import requests
# api-endpoint
URL = "https://api.fondy.eu/api/settlement"
# defining a params dict for the parameters to be sent to the API
data =
"order": {
"server_callback_url": "http://site.id/callback",
"currency": "UAH",
"amount": "1400",
"order_type": "settlement",
"response_url": "http://site.id/test/responsepage/",
"order_id": "test1234561467462099.19",
"operation_id": "test1234561467462099.19",
"order_desc": "test order",
"merchant_id": 700001,
"receiver": [
{
"requisites": {
"amount": 100,
"merchant_id": 500001
},
"type": "merchant"
},{
"requisites": {
"amount": 200,
"merchant_id": 600001
},
"type": "merchant"
},
]
}
# sending get request and saving the response as response object
r = requests.POST(url = URL, data= data)
# extracting data in json format
data = r.json()
Maybe you would like to try the API before writing code, there is tool like postman to do this quickly :)

Access meta reply message

My backed is giving me some information about the reply in a meta field. For example, when going to #/phoneNumbers/phonelocations/index a request to /api/phonelocations is sent, and this is the data received:
{
"meta": {
"api_action": "find_all",
"api_id": "phonelocations",
"content_type": "application/json",
"error_code": 200,
"errors": [
{
"admin_message": "",
"code": 200,
"message": ""
}
],
"message": "Successfully read phonelocations",
"success": true
},
"phonelocations": [
{
"_id": "0",
"city": "Berlin",
"count": 10,
"country": "DE",
"country_name": "Germany",
"loctype": "GEO",
"loctype_human": "Geographical number",
"subtype": "49GEO",
"subtype_human": "German geographical number",
"type": "phonelocation-faketype"
},
...
]
}
This is present in all replies coming from the backend. I would like to use the message in _reply_meta.message to display it to the user. Is there a standard way in Ember to access the meta information of the replies?
Just use store.metadataFor(type), in your case:
var meta = this.store.metadataFor('phonelocation');
// all metadata is in meta object
meta.message // => "Successfully read phonelocations"
See this in action http://jsfiddle.net/marciojunior/3vfQD/