{"id":24291634,"url":"https://github.com/thomastjdev/nim_awsses_sns","last_synced_at":"2026-06-08T05:31:07.793Z","repository":{"id":270971795,"uuid":"912001220","full_name":"ThomasTJdev/nim_awsSES_SNS","owner":"ThomasTJdev","description":"Handle AWS SES bounce and complaint notifications through AWS SNS","archived":false,"fork":false,"pushed_at":"2026-01-15T12:32:14.000Z","size":19,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-15T16:53:48.897Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThomasTJdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-01-04T12:34:58.000Z","updated_at":"2026-01-15T12:32:12.000Z","dependencies_parsed_at":"2025-01-04T13:48:05.983Z","dependency_job_id":"48db53dc-ec3e-4a05-8d4e-b6b782ff35c6","html_url":"https://github.com/ThomasTJdev/nim_awsSES_SNS","commit_stats":null,"previous_names":["thomastjdev/nim_awsses_sns"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ThomasTJdev/nim_awsSES_SNS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_awsSES_SNS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_awsSES_SNS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_awsSES_SNS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_awsSES_SNS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThomasTJdev","download_url":"https://codeload.github.com/ThomasTJdev/nim_awsSES_SNS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThomasTJdev%2Fnim_awsSES_SNS/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34050225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-16T14:56:16.417Z","updated_at":"2026-06-08T05:31:07.787Z","avatar_url":"https://github.com/ThomasTJdev.png","language":"Nim","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# AWS SES bounce and complaint handling through AWS SNS\nThis library is used to handle AWS SES bounce and complaint notifications through\nAWS SNS. The library is able to parse the JSON message from AWS SNS and extract\nthe relevant information.\n\n1. Create a configuration set with event notifications and a SNStopic.\n2. Open AWS SES console and create a verified identity and assign the configuration set.\n3. In SNS confirm the subscription to the topic.\n\n\n# Learn more about AWS SES use of SNS\nhttps://docs.aws.amazon.com/ses/latest/dg/notification-contents.html\nhttps://docs.aws.amazon.com/ses/latest/dg/event-publishing-retrieving-sns-examples.html\n\n\n# Test emails from AWS SES for bounce and complaint\nUse these to avoid sending emails to real addresses and getting blacklisted.\n```\nsuccess@simulator.amazonses.com         # Successful delivery\nbounce@simulator.amazonses.com          # Bounce\nooto@simulator.amazonses.com            # Automatic Response\ncomplaint@simulator.amazonses.com       # Complaint\nsuppressionlist@simulator.amazonses.com # Recipient address on suppression list\n```\n\n\n# SMTP_SES\nWe cannot use the standard smtp library, https://github.com/nim-lang/smtp, to\nsend emails, since it does not support returning the last server reply which\ncontains the message ID. A PR has been sent: https://github.com/nim-lang/smtp/pull/18\n\nTo fix this import `smtp_ses` directly like `awsSES_SNS/smtp_ses` or just import\nthe full module `awsSES_SNS` which will import `smtp_ses` as well.\n\n```nim\nimport awsSES_SNS\n\n# Using the sendMailGetReply allows to capture the message ID\nlet reply = client.sendMailGetReply(fromAddr, toAddr, msg)\necho reply\n# =\u003e 0101017b7b7b7b7b-7b7b7b7b-324reewsd\n```\n\n# Email formatting\nPlease refer to the package https://github.com/enthus1ast/nimMime for email\nformatting. Attachments, reply-to, etc.\n\n\n# Example\nThe example below uses mummy to create a simple server that listens for incoming\nSNS messages from AWS SES.\n\nThe example below is available in the tests folder as well.\n\n```nim\nimport\n  std/[\n    json,\n    strutils\n  ]\n\nimport mummy, mummy/routers\nimport mummy_utils\n\nimport awsSES_SNS\n\nvar router: Router\nrouter.post(\"/api/webhooks/incoming/sns\", proc(request: Request) =\n  echo \"Received SNS message POST\"\n\n  let (snsSuccess, snsMsg) = snsParseJson(request.body)\n  if not snsSuccess:\n    echo \"Error parsing SNS JSON\"\n    resp Http400\n\n  # Case through the different types of events\n  case snsParseEventType(snsMsg)\n  of SNSSubscriptionConfirmation:\n    let sub = snsSubscriptionConfirmation(snsMsg)\n    echo sub.message\n    echo sub.subscribeURL\n\n  of Bounce:\n    let mailBounce = snsParseBounce(snsMsg)\n    for mail in mailBounce:\n      echo mail.email \u0026 \" - \" \u0026 $mail.bounceType \u0026 \" - \" \u0026 $mail.bounceSubType \u0026 \" - \" \u0026 mail.messageID\n\n  of Complaint:\n    let mailComplaint = snsParseComplaint(snsMsg)\n    if not mailComplaint.parsingSucceeded:\n      echo \"Error parsing complaint\"\n      resp Http400\n    for mail in mailComplaint:\n      echo mail.email \u0026 \" - \" \u0026 $mail.feedbackType \u0026 \" - \" \u0026 mail.messageID\n\n  of Delivery:\n    let mailDelivery = snsParseDelivery(snsMsg)\n    if not mailDelivery.parsingSucceeded:\n      echo \"Error parsing delivery\"\n      resp Http400\n    echo $mailDelivery.email \u0026 \" - \" \u0026 mailDelivery.messageID\n\n  of Open:\n    let mailOpen = snsParseOpen(snsMsg)\n    if not mailOpen.parsingSucceeded:\n      echo \"Error parsing open\"\n      resp Http400\n    echo mailOpen.ipAddress \u0026 \" - \" \u0026 mailOpen.timestamp \u0026 \" - \" \u0026 mailOpen.messageID\n\n  of Click:\n    let mailClick = snsParseClick(snsMsg)\n    echo mailClick.link \u0026 \" - \" \u0026 mailClick.timestamp \u0026 \" - \" \u0026 mailClick.messageID\n\n  else:\n    echo \"Unknown event type\"\n\n  resp Http200\n)\n\nrouter.get(\"/sendmail\", proc(request: Request) =\n\n  let messageID = client.sendMailGetReply(fromAddr, toAddr, msg)\n  # Save the messageID for later reference, e.g. for tracking opens and clicks.\n\n  resp Http200\n)\n\n\nlet server = newServer(router)\necho \"Serving on http://localhost:8080\"\nserver.serve(Port(8080))\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomastjdev%2Fnim_awsses_sns","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomastjdev%2Fnim_awsses_sns","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomastjdev%2Fnim_awsses_sns/lists"}