Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/boto/ses/connection.py @ 0:d30785e31577 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:18:57 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:d30785e31577 |
|---|---|
| 1 # Copyright (c) 2010 Mitch Garnaat http://garnaat.org/ | |
| 2 # Copyright (c) 2011 Harry Marr http://hmarr.com/ | |
| 3 # | |
| 4 # Permission is hereby granted, free of charge, to any person obtaining a | |
| 5 # copy of this software and associated documentation files (the | |
| 6 # "Software"), to deal in the Software without restriction, including | |
| 7 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
| 8 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
| 9 # persons to whom the Software is furnished to do so, subject to the fol- | |
| 10 # lowing conditions: | |
| 11 # | |
| 12 # The above copyright notice and this permission notice shall be included | |
| 13 # in all copies or substantial portions of the Software. | |
| 14 # | |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 16 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
| 17 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
| 18 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 19 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 21 # IN THE SOFTWARE. | |
| 22 import re | |
| 23 import base64 | |
| 24 | |
| 25 from boto.compat import six, urllib | |
| 26 from boto.connection import AWSAuthConnection | |
| 27 from boto.exception import BotoServerError | |
| 28 from boto.regioninfo import RegionInfo | |
| 29 import boto | |
| 30 import boto.jsonresponse | |
| 31 from boto.ses import exceptions as ses_exceptions | |
| 32 | |
| 33 | |
| 34 class SESConnection(AWSAuthConnection): | |
| 35 | |
| 36 ResponseError = BotoServerError | |
| 37 DefaultRegionName = 'us-east-1' | |
| 38 DefaultRegionEndpoint = 'email.us-east-1.amazonaws.com' | |
| 39 APIVersion = '2010-12-01' | |
| 40 | |
| 41 def __init__(self, aws_access_key_id=None, aws_secret_access_key=None, | |
| 42 is_secure=True, port=None, proxy=None, proxy_port=None, | |
| 43 proxy_user=None, proxy_pass=None, debug=0, | |
| 44 https_connection_factory=None, region=None, path='/', | |
| 45 security_token=None, validate_certs=True, profile_name=None): | |
| 46 if not region: | |
| 47 region = RegionInfo(self, self.DefaultRegionName, | |
| 48 self.DefaultRegionEndpoint) | |
| 49 self.region = region | |
| 50 super(SESConnection, self).__init__(self.region.endpoint, | |
| 51 aws_access_key_id, aws_secret_access_key, | |
| 52 is_secure, port, proxy, proxy_port, | |
| 53 proxy_user, proxy_pass, debug, | |
| 54 https_connection_factory, path, | |
| 55 security_token=security_token, | |
| 56 validate_certs=validate_certs, | |
| 57 profile_name=profile_name) | |
| 58 | |
| 59 def _required_auth_capability(self): | |
| 60 return ['ses'] | |
| 61 | |
| 62 def _build_list_params(self, params, items, label): | |
| 63 """Add an AWS API-compatible parameter list to a dictionary. | |
| 64 | |
| 65 :type params: dict | |
| 66 :param params: The parameter dictionary | |
| 67 | |
| 68 :type items: list | |
| 69 :param items: Items to be included in the list | |
| 70 | |
| 71 :type label: string | |
| 72 :param label: The parameter list's name | |
| 73 """ | |
| 74 if isinstance(items, six.string_types): | |
| 75 items = [items] | |
| 76 for i in range(1, len(items) + 1): | |
| 77 params['%s.%d' % (label, i)] = items[i - 1] | |
| 78 | |
| 79 def _make_request(self, action, params=None): | |
| 80 """Make a call to the SES API. | |
| 81 | |
| 82 :type action: string | |
| 83 :param action: The API method to use (e.g. SendRawEmail) | |
| 84 | |
| 85 :type params: dict | |
| 86 :param params: Parameters that will be sent as POST data with the API | |
| 87 call. | |
| 88 """ | |
| 89 ct = 'application/x-www-form-urlencoded; charset=UTF-8' | |
| 90 headers = {'Content-Type': ct} | |
| 91 params = params or {} | |
| 92 params['Action'] = action | |
| 93 | |
| 94 for k, v in params.items(): | |
| 95 if isinstance(v, six.text_type): # UTF-8 encode only if it's Unicode | |
| 96 params[k] = v.encode('utf-8') | |
| 97 | |
| 98 response = super(SESConnection, self).make_request( | |
| 99 'POST', | |
| 100 '/', | |
| 101 headers=headers, | |
| 102 data=urllib.parse.urlencode(params) | |
| 103 ) | |
| 104 body = response.read().decode('utf-8') | |
| 105 if response.status == 200: | |
| 106 list_markers = ('VerifiedEmailAddresses', 'Identities', | |
| 107 'DkimTokens', 'DkimAttributes', | |
| 108 'VerificationAttributes', 'SendDataPoints') | |
| 109 item_markers = ('member', 'item', 'entry') | |
| 110 | |
| 111 e = boto.jsonresponse.Element(list_marker=list_markers, | |
| 112 item_marker=item_markers) | |
| 113 h = boto.jsonresponse.XmlHandler(e, None) | |
| 114 h.parse(body) | |
| 115 return e | |
| 116 else: | |
| 117 # HTTP codes other than 200 are considered errors. Go through | |
| 118 # some error handling to determine which exception gets raised, | |
| 119 self._handle_error(response, body) | |
| 120 | |
| 121 def _handle_error(self, response, body): | |
| 122 """ | |
| 123 Handle raising the correct exception, depending on the error. Many | |
| 124 errors share the same HTTP response code, meaning we have to get really | |
| 125 kludgey and do string searches to figure out what went wrong. | |
| 126 """ | |
| 127 boto.log.error('%s %s' % (response.status, response.reason)) | |
| 128 boto.log.error('%s' % body) | |
| 129 | |
| 130 if "Address blacklisted." in body: | |
| 131 # Delivery failures happened frequently enough with the recipient's | |
| 132 # email address for Amazon to blacklist it. After a day or three, | |
| 133 # they'll be automatically removed, and delivery can be attempted | |
| 134 # again (if you write the code to do so in your application). | |
| 135 ExceptionToRaise = ses_exceptions.SESAddressBlacklistedError | |
| 136 exc_reason = "Address blacklisted." | |
| 137 elif "Email address is not verified." in body: | |
| 138 # This error happens when the "Reply-To" value passed to | |
| 139 # send_email() hasn't been verified yet. | |
| 140 ExceptionToRaise = ses_exceptions.SESAddressNotVerifiedError | |
| 141 exc_reason = "Email address is not verified." | |
| 142 elif "Daily message quota exceeded." in body: | |
| 143 # Encountered when your account exceeds the maximum total number | |
| 144 # of emails per 24 hours. | |
| 145 ExceptionToRaise = ses_exceptions.SESDailyQuotaExceededError | |
| 146 exc_reason = "Daily message quota exceeded." | |
| 147 elif "Maximum sending rate exceeded." in body: | |
| 148 # Your account has sent above its allowed requests a second rate. | |
| 149 ExceptionToRaise = ses_exceptions.SESMaxSendingRateExceededError | |
| 150 exc_reason = "Maximum sending rate exceeded." | |
| 151 elif "Domain ends with dot." in body: | |
| 152 # Recipient address ends with a dot/period. This is invalid. | |
| 153 ExceptionToRaise = ses_exceptions.SESDomainEndsWithDotError | |
| 154 exc_reason = "Domain ends with dot." | |
| 155 elif "Local address contains control or whitespace" in body: | |
| 156 # I think this pertains to the recipient address. | |
| 157 ExceptionToRaise = ses_exceptions.SESLocalAddressCharacterError | |
| 158 exc_reason = "Local address contains control or whitespace." | |
| 159 elif "Illegal address" in body: | |
| 160 # A clearly mal-formed address. | |
| 161 ExceptionToRaise = ses_exceptions.SESIllegalAddressError | |
| 162 exc_reason = "Illegal address" | |
| 163 # The re.search is to distinguish from the | |
| 164 # SESAddressNotVerifiedError error above. | |
| 165 elif re.search('Identity.*is not verified', body): | |
| 166 ExceptionToRaise = ses_exceptions.SESIdentityNotVerifiedError | |
| 167 exc_reason = "Identity is not verified." | |
| 168 elif "ownership not confirmed" in body: | |
| 169 ExceptionToRaise = ses_exceptions.SESDomainNotConfirmedError | |
| 170 exc_reason = "Domain ownership is not confirmed." | |
| 171 else: | |
| 172 # This is either a common AWS error, or one that we don't devote | |
| 173 # its own exception to. | |
| 174 ExceptionToRaise = self.ResponseError | |
| 175 exc_reason = response.reason | |
| 176 | |
| 177 raise ExceptionToRaise(response.status, exc_reason, body) | |
| 178 | |
| 179 def send_email(self, source, subject, body, to_addresses, | |
| 180 cc_addresses=None, bcc_addresses=None, | |
| 181 format='text', reply_addresses=None, | |
| 182 return_path=None, text_body=None, html_body=None): | |
| 183 """Composes an email message based on input data, and then immediately | |
| 184 queues the message for sending. | |
| 185 | |
| 186 :type source: string | |
| 187 :param source: The sender's email address. | |
| 188 | |
| 189 :type subject: string | |
| 190 :param subject: The subject of the message: A short summary of the | |
| 191 content, which will appear in the recipient's inbox. | |
| 192 | |
| 193 :type body: string | |
| 194 :param body: The message body. | |
| 195 | |
| 196 :type to_addresses: list of strings or string | |
| 197 :param to_addresses: The To: field(s) of the message. | |
| 198 | |
| 199 :type cc_addresses: list of strings or string | |
| 200 :param cc_addresses: The CC: field(s) of the message. | |
| 201 | |
| 202 :type bcc_addresses: list of strings or string | |
| 203 :param bcc_addresses: The BCC: field(s) of the message. | |
| 204 | |
| 205 :type format: string | |
| 206 :param format: The format of the message's body, must be either "text" | |
| 207 or "html". | |
| 208 | |
| 209 :type reply_addresses: list of strings or string | |
| 210 :param reply_addresses: The reply-to email address(es) for the | |
| 211 message. If the recipient replies to the | |
| 212 message, each reply-to address will | |
| 213 receive the reply. | |
| 214 | |
| 215 :type return_path: string | |
| 216 :param return_path: The email address to which bounce notifications are | |
| 217 to be forwarded. If the message cannot be delivered | |
| 218 to the recipient, then an error message will be | |
| 219 returned from the recipient's ISP; this message | |
| 220 will then be forwarded to the email address | |
| 221 specified by the ReturnPath parameter. | |
| 222 | |
| 223 :type text_body: string | |
| 224 :param text_body: The text body to send with this email. | |
| 225 | |
| 226 :type html_body: string | |
| 227 :param html_body: The html body to send with this email. | |
| 228 | |
| 229 """ | |
| 230 format = format.lower().strip() | |
| 231 if body is not None: | |
| 232 if format == "text": | |
| 233 if text_body is not None: | |
| 234 raise Warning("You've passed in both a body and a " | |
| 235 "text_body; please choose one or the other.") | |
| 236 text_body = body | |
| 237 else: | |
| 238 if html_body is not None: | |
| 239 raise Warning("You've passed in both a body and an " | |
| 240 "html_body; please choose one or the other.") | |
| 241 html_body = body | |
| 242 | |
| 243 params = { | |
| 244 'Source': source, | |
| 245 'Message.Subject.Data': subject, | |
| 246 } | |
| 247 | |
| 248 if return_path: | |
| 249 params['ReturnPath'] = return_path | |
| 250 | |
| 251 if html_body is not None: | |
| 252 params['Message.Body.Html.Data'] = html_body | |
| 253 if text_body is not None: | |
| 254 params['Message.Body.Text.Data'] = text_body | |
| 255 | |
| 256 if(format not in ("text", "html")): | |
| 257 raise ValueError("'format' argument must be 'text' or 'html'") | |
| 258 | |
| 259 if(not (html_body or text_body)): | |
| 260 raise ValueError("No text or html body found for mail") | |
| 261 | |
| 262 self._build_list_params(params, to_addresses, | |
| 263 'Destination.ToAddresses.member') | |
| 264 if cc_addresses: | |
| 265 self._build_list_params(params, cc_addresses, | |
| 266 'Destination.CcAddresses.member') | |
| 267 | |
| 268 if bcc_addresses: | |
| 269 self._build_list_params(params, bcc_addresses, | |
| 270 'Destination.BccAddresses.member') | |
| 271 | |
| 272 if reply_addresses: | |
| 273 self._build_list_params(params, reply_addresses, | |
| 274 'ReplyToAddresses.member') | |
| 275 | |
| 276 return self._make_request('SendEmail', params) | |
| 277 | |
| 278 def send_raw_email(self, raw_message, source=None, destinations=None): | |
| 279 """Sends an email message, with header and content specified by the | |
| 280 client. The SendRawEmail action is useful for sending multipart MIME | |
| 281 emails, with attachments or inline content. The raw text of the message | |
| 282 must comply with Internet email standards; otherwise, the message | |
| 283 cannot be sent. | |
| 284 | |
| 285 :type source: string | |
| 286 :param source: The sender's email address. Amazon's docs say: | |
| 287 | |
| 288 If you specify the Source parameter, then bounce notifications and | |
| 289 complaints will be sent to this email address. This takes precedence | |
| 290 over any Return-Path header that you might include in the raw text of | |
| 291 the message. | |
| 292 | |
| 293 :type raw_message: string | |
| 294 :param raw_message: The raw text of the message. The client is | |
| 295 responsible for ensuring the following: | |
| 296 | |
| 297 - Message must contain a header and a body, separated by a blank line. | |
| 298 - All required header fields must be present. | |
| 299 - Each part of a multipart MIME message must be formatted properly. | |
| 300 - MIME content types must be among those supported by Amazon SES. | |
| 301 Refer to the Amazon SES Developer Guide for more details. | |
| 302 - Content must be base64-encoded, if MIME requires it. | |
| 303 | |
| 304 :type destinations: list of strings or string | |
| 305 :param destinations: A list of destinations for the message. | |
| 306 | |
| 307 """ | |
| 308 | |
| 309 if isinstance(raw_message, six.text_type): | |
| 310 raw_message = raw_message.encode('utf-8') | |
| 311 | |
| 312 params = { | |
| 313 'RawMessage.Data': base64.b64encode(raw_message), | |
| 314 } | |
| 315 | |
| 316 if source: | |
| 317 params['Source'] = source | |
| 318 | |
| 319 if destinations: | |
| 320 self._build_list_params(params, destinations, | |
| 321 'Destinations.member') | |
| 322 | |
| 323 return self._make_request('SendRawEmail', params) | |
| 324 | |
| 325 def list_verified_email_addresses(self): | |
| 326 """Fetch a list of the email addresses that have been verified. | |
| 327 | |
| 328 :rtype: dict | |
| 329 :returns: A ListVerifiedEmailAddressesResponse structure. Note that | |
| 330 keys must be unicode strings. | |
| 331 """ | |
| 332 return self._make_request('ListVerifiedEmailAddresses') | |
| 333 | |
| 334 def get_send_quota(self): | |
| 335 """Fetches the user's current activity limits. | |
| 336 | |
| 337 :rtype: dict | |
| 338 :returns: A GetSendQuotaResponse structure. Note that keys must be | |
| 339 unicode strings. | |
| 340 """ | |
| 341 return self._make_request('GetSendQuota') | |
| 342 | |
| 343 def get_send_statistics(self): | |
| 344 """Fetches the user's sending statistics. The result is a list of data | |
| 345 points, representing the last two weeks of sending activity. | |
| 346 | |
| 347 Each data point in the list contains statistics for a 15-minute | |
| 348 interval. | |
| 349 | |
| 350 :rtype: dict | |
| 351 :returns: A GetSendStatisticsResponse structure. Note that keys must be | |
| 352 unicode strings. | |
| 353 """ | |
| 354 return self._make_request('GetSendStatistics') | |
| 355 | |
| 356 def delete_verified_email_address(self, email_address): | |
| 357 """Deletes the specified email address from the list of verified | |
| 358 addresses. | |
| 359 | |
| 360 :type email_adddress: string | |
| 361 :param email_address: The email address to be removed from the list of | |
| 362 verified addreses. | |
| 363 | |
| 364 :rtype: dict | |
| 365 :returns: A DeleteVerifiedEmailAddressResponse structure. Note that | |
| 366 keys must be unicode strings. | |
| 367 """ | |
| 368 return self._make_request('DeleteVerifiedEmailAddress', { | |
| 369 'EmailAddress': email_address, | |
| 370 }) | |
| 371 | |
| 372 def verify_email_address(self, email_address): | |
| 373 """Verifies an email address. This action causes a confirmation email | |
| 374 message to be sent to the specified address. | |
| 375 | |
| 376 :type email_adddress: string | |
| 377 :param email_address: The email address to be verified. | |
| 378 | |
| 379 :rtype: dict | |
| 380 :returns: A VerifyEmailAddressResponse structure. Note that keys must | |
| 381 be unicode strings. | |
| 382 """ | |
| 383 return self._make_request('VerifyEmailAddress', { | |
| 384 'EmailAddress': email_address, | |
| 385 }) | |
| 386 | |
| 387 def verify_domain_dkim(self, domain): | |
| 388 """ | |
| 389 Returns a set of DNS records, or tokens, that must be published in the | |
| 390 domain name's DNS to complete the DKIM verification process. These | |
| 391 tokens are DNS ``CNAME`` records that point to DKIM public keys hosted | |
| 392 by Amazon SES. To complete the DKIM verification process, these tokens | |
| 393 must be published in the domain's DNS. The tokens must remain | |
| 394 published in order for Easy DKIM signing to function correctly. | |
| 395 | |
| 396 After the tokens are added to the domain's DNS, Amazon SES will be able | |
| 397 to DKIM-sign email originating from that domain. To enable or disable | |
| 398 Easy DKIM signing for a domain, use the ``SetIdentityDkimEnabled`` | |
| 399 action. For more information about Easy DKIM, go to the `Amazon SES | |
| 400 Developer Guide | |
| 401 <http://docs.amazonwebservices.com/ses/latest/DeveloperGuide>`_. | |
| 402 | |
| 403 :type domain: string | |
| 404 :param domain: The domain name. | |
| 405 | |
| 406 """ | |
| 407 return self._make_request('VerifyDomainDkim', { | |
| 408 'Domain': domain, | |
| 409 }) | |
| 410 | |
| 411 def set_identity_dkim_enabled(self, identity, dkim_enabled): | |
| 412 """Enables or disables DKIM signing of email sent from an identity. | |
| 413 | |
| 414 * If Easy DKIM signing is enabled for a domain name identity (e.g., | |
| 415 * ``example.com``), | |
| 416 then Amazon SES will DKIM-sign all email sent by addresses under that | |
| 417 domain name (e.g., ``user@example.com``) | |
| 418 * If Easy DKIM signing is enabled for an email address, then Amazon SES | |
| 419 will DKIM-sign all email sent by that email address. | |
| 420 | |
| 421 For email addresses (e.g., ``user@example.com``), you can only enable | |
| 422 Easy DKIM signing if the corresponding domain (e.g., ``example.com``) | |
| 423 has been set up for Easy DKIM using the AWS Console or the | |
| 424 ``VerifyDomainDkim`` action. | |
| 425 | |
| 426 :type identity: string | |
| 427 :param identity: An email address or domain name. | |
| 428 | |
| 429 :type dkim_enabled: bool | |
| 430 :param dkim_enabled: Specifies whether or not to enable DKIM signing. | |
| 431 | |
| 432 """ | |
| 433 return self._make_request('SetIdentityDkimEnabled', { | |
| 434 'Identity': identity, | |
| 435 'DkimEnabled': 'true' if dkim_enabled else 'false' | |
| 436 }) | |
| 437 | |
| 438 def get_identity_dkim_attributes(self, identities): | |
| 439 """Get attributes associated with a list of verified identities. | |
| 440 | |
| 441 Given a list of verified identities (email addresses and/or domains), | |
| 442 returns a structure describing identity notification attributes. | |
| 443 | |
| 444 :type identities: list | |
| 445 :param identities: A list of verified identities (email addresses | |
| 446 and/or domains). | |
| 447 | |
| 448 """ | |
| 449 params = {} | |
| 450 self._build_list_params(params, identities, 'Identities.member') | |
| 451 return self._make_request('GetIdentityDkimAttributes', params) | |
| 452 | |
| 453 def list_identities(self): | |
| 454 """Returns a list containing all of the identities (email addresses | |
| 455 and domains) for a specific AWS Account, regardless of | |
| 456 verification status. | |
| 457 | |
| 458 :rtype: dict | |
| 459 :returns: A ListIdentitiesResponse structure. Note that | |
| 460 keys must be unicode strings. | |
| 461 """ | |
| 462 return self._make_request('ListIdentities') | |
| 463 | |
| 464 def get_identity_verification_attributes(self, identities): | |
| 465 """Given a list of identities (email addresses and/or domains), | |
| 466 returns the verification status and (for domain identities) | |
| 467 the verification token for each identity. | |
| 468 | |
| 469 :type identities: list of strings or string | |
| 470 :param identities: List of identities. | |
| 471 | |
| 472 :rtype: dict | |
| 473 :returns: A GetIdentityVerificationAttributesResponse structure. | |
| 474 Note that keys must be unicode strings. | |
| 475 """ | |
| 476 params = {} | |
| 477 self._build_list_params(params, identities, | |
| 478 'Identities.member') | |
| 479 return self._make_request('GetIdentityVerificationAttributes', params) | |
| 480 | |
| 481 def verify_domain_identity(self, domain): | |
| 482 """Verifies a domain. | |
| 483 | |
| 484 :type domain: string | |
| 485 :param domain: The domain to be verified. | |
| 486 | |
| 487 :rtype: dict | |
| 488 :returns: A VerifyDomainIdentityResponse structure. Note that | |
| 489 keys must be unicode strings. | |
| 490 """ | |
| 491 return self._make_request('VerifyDomainIdentity', { | |
| 492 'Domain': domain, | |
| 493 }) | |
| 494 | |
| 495 def verify_email_identity(self, email_address): | |
| 496 """Verifies an email address. This action causes a confirmation | |
| 497 email message to be sent to the specified address. | |
| 498 | |
| 499 :type email_adddress: string | |
| 500 :param email_address: The email address to be verified. | |
| 501 | |
| 502 :rtype: dict | |
| 503 :returns: A VerifyEmailIdentityResponse structure. Note that keys must | |
| 504 be unicode strings. | |
| 505 """ | |
| 506 return self._make_request('VerifyEmailIdentity', { | |
| 507 'EmailAddress': email_address, | |
| 508 }) | |
| 509 | |
| 510 def delete_identity(self, identity): | |
| 511 """Deletes the specified identity (email address or domain) from | |
| 512 the list of verified identities. | |
| 513 | |
| 514 :type identity: string | |
| 515 :param identity: The identity to be deleted. | |
| 516 | |
| 517 :rtype: dict | |
| 518 :returns: A DeleteIdentityResponse structure. Note that keys must | |
| 519 be unicode strings. | |
| 520 """ | |
| 521 return self._make_request('DeleteIdentity', { | |
| 522 'Identity': identity, | |
| 523 }) | |
| 524 | |
| 525 def set_identity_notification_topic(self, identity, notification_type, sns_topic=None): | |
| 526 """Sets an SNS topic to publish bounce or complaint notifications for | |
| 527 emails sent with the given identity as the Source. Publishing to topics | |
| 528 may only be disabled when feedback forwarding is enabled. | |
| 529 | |
| 530 :type identity: string | |
| 531 :param identity: An email address or domain name. | |
| 532 | |
| 533 :type notification_type: string | |
| 534 :param notification_type: The type of feedback notifications that will | |
| 535 be published to the specified topic. | |
| 536 Valid Values: Bounce | Complaint | Delivery | |
| 537 | |
| 538 :type sns_topic: string or None | |
| 539 :param sns_topic: The Amazon Resource Name (ARN) of the Amazon Simple | |
| 540 Notification Service (Amazon SNS) topic. | |
| 541 """ | |
| 542 params = { | |
| 543 'Identity': identity, | |
| 544 'NotificationType': notification_type | |
| 545 } | |
| 546 if sns_topic: | |
| 547 params['SnsTopic'] = sns_topic | |
| 548 return self._make_request('SetIdentityNotificationTopic', params) | |
| 549 | |
| 550 def set_identity_feedback_forwarding_enabled(self, identity, forwarding_enabled=True): | |
| 551 """ | |
| 552 Enables or disables SES feedback notification via email. | |
| 553 Feedback forwarding may only be disabled when both complaint and | |
| 554 bounce topics are set. | |
| 555 | |
| 556 :type identity: string | |
| 557 :param identity: An email address or domain name. | |
| 558 | |
| 559 :type forwarding_enabled: bool | |
| 560 :param forwarding_enabled: Specifies whether or not to enable feedback forwarding. | |
| 561 """ | |
| 562 return self._make_request('SetIdentityFeedbackForwardingEnabled', { | |
| 563 'Identity': identity, | |
| 564 'ForwardingEnabled': 'true' if forwarding_enabled else 'false' | |
| 565 }) |
