{"action":"closed","number":3,"pull_request":{"url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls/3","id":37097969,"html_url":"https://github.com/thoughtbot/griddler-cloudmailin/pull/3","diff_url":"https://github.com/thoughtbot/griddler-cloudmailin/pull/3.diff","patch_url":"https://github.com/thoughtbot/griddler-cloudmailin/pull/3.patch","issue_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/issues/3","number":3,"state":"closed","locked":false,"title":"Correctly handle emails where CloudMailin has been BCCed","user":{"login":"dominicsayers","id":34939,"avatar_url":"https://avatars.githubusercontent.com/u/34939?v=3","gravatar_id":"","url":"https://api.github.com/users/dominicsayers","html_url":"https://github.com/dominicsayers","followers_url":"https://api.github.com/users/dominicsayers/followers","following_url":"https://api.github.com/users/dominicsayers/following{/other_user}","gists_url":"https://api.github.com/users/dominicsayers/gists{/gist_id}","starred_url":"https://api.github.com/users/dominicsayers/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dominicsayers/subscriptions","organizations_url":"https://api.github.com/users/dominicsayers/orgs","repos_url":"https://api.github.com/users/dominicsayers/repos","events_url":"https://api.github.com/users/dominicsayers/events{/privacy}","received_events_url":"https://api.github.com/users/dominicsayers/received_events","type":"User","site_admin":false},"body":"This pull request is designed to achieve two things:\r\n\r\n1.  To make the CloudMailin adapter make better use of the JSON that CloudMailin sends today.\r\n2.  To handle the case where CloudMailin is processing an email that has been BCCed to it\r\n\r\nSo as not to break Griddler itself, I've chosen to put the BCCed address in the `bcc` field of the normalized params.\r\n\r\nI've minimized the changes I've made as far as possible. Here's a walkthrough of what I've had to change in `adapter.rb` :\r\n\r\n1.  I've built the `to` array from `[:headers][:To]` instead of `[:envelope][:to]` because the envelope contains only the bare address and not the recipient's name. Also, Cloudmailin uses `[:envelope][:to]` for the BCCed recipient if any.\r\n2.  For similar reasons, I've used `[:headers][:From]` instead of `[:envelope][:from]` because the envelope contains only the email address and not the name of the sender.\r\n3.  The `bcc` field is only added to the normalized params if the CloudMailin recipient was BCCed.\r\n4.  To establish whether the `[:envelope][:to]` field is a Bcc: or a To: recipient, we have to compare the email address with all the email addresses in `[:headers][:To]`. Unfortunately this means calling `Griddler::EmailParser` for each of them, an expensive but unavoidable step.\r\n\r\nIn the tests, I've modified the service params to reflect more accurately what CloudMailin actually sends. I've also added tests to show my expectations of how we handle the BCC case.\r\n\r\n1.  The real-world `[:envelope][:to]` and `[:envelope][:from]` fields are always just a bare email address.\r\n2.  I've added `[:headers][:To]` and `[:headers][:From]` to the service params because these are the fields we now use.\r\n3.  In the tests where the recipient is BCCed, you can see that the `[:headers][:To]` field does not contain the `[:envelope][:to]` address\r\n\r\nHere are two real-world messages from CloudMailin https://gist.github.com/dominicsayers/c40b08b7d581aa54e4d0 and https://gist.github.com/dominicsayers/67f4884b797a0f975396. They are intended to be very similar but were sent from different email clients. You can see that the message sent from Gmail has `[:headers][:Bcc]` set but the one from the OS X Mail app doesn't. Go figure.","created_at":"2015-06-06T22:40:57Z","updated_at":"2015-06-08T13:23:29Z","closed_at":"2015-06-08T13:23:29Z","merged_at":null,"merge_commit_sha":"f06c05a37bfe08bac9a080eac431cb2bf068d6d7","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls/3/commits","review_comments_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls/3/comments","review_comment_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/issues/3/comments","statuses_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/statuses/8ce0f6b0223e7b986a81a96511d512c479b12171","head":{"label":"Xenapto:master","ref":"master","sha":"8ce0f6b0223e7b986a81a96511d512c479b12171","user":{"login":"Xenapto","id":1461353,"avatar_url":"https://avatars.githubusercontent.com/u/1461353?v=3","gravatar_id":"","url":"https://api.github.com/users/Xenapto","html_url":"https://github.com/Xenapto","followers_url":"https://api.github.com/users/Xenapto/followers","following_url":"https://api.github.com/users/Xenapto/following{/other_user}","gists_url":"https://api.github.com/users/Xenapto/gists{/gist_id}","starred_url":"https://api.github.com/users/Xenapto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Xenapto/subscriptions","organizations_url":"https://api.github.com/users/Xenapto/orgs","repos_url":"https://api.github.com/users/Xenapto/repos","events_url":"https://api.github.com/users/Xenapto/events{/privacy}","received_events_url":"https://api.github.com/users/Xenapto/received_events","type":"Organization","site_admin":false},"repo":{"id":36945855,"name":"griddler-cloudmailin","full_name":"Xenapto/griddler-cloudmailin","owner":{"login":"Xenapto","id":1461353,"avatar_url":"https://avatars.githubusercontent.com/u/1461353?v=3","gravatar_id":"","url":"https://api.github.com/users/Xenapto","html_url":"https://github.com/Xenapto","followers_url":"https://api.github.com/users/Xenapto/followers","following_url":"https://api.github.com/users/Xenapto/following{/other_user}","gists_url":"https://api.github.com/users/Xenapto/gists{/gist_id}","starred_url":"https://api.github.com/users/Xenapto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Xenapto/subscriptions","organizations_url":"https://api.github.com/users/Xenapto/orgs","repos_url":"https://api.github.com/users/Xenapto/repos","events_url":"https://api.github.com/users/Xenapto/events{/privacy}","received_events_url":"https://api.github.com/users/Xenapto/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Xenapto/griddler-cloudmailin","description":"","fork":true,"url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin","forks_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/forks","keys_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/teams","hooks_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/hooks","issue_events_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/issues/events{/number}","events_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/events","assignees_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/assignees{/user}","branches_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/branches{/branch}","tags_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/tags","blobs_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/git/refs{/sha}","trees_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/statuses/{sha}","languages_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/languages","stargazers_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/stargazers","contributors_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/contributors","subscribers_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/subscribers","subscription_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/subscription","commits_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/commits{/sha}","git_commits_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/git/commits{/sha}","comments_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/comments{/number}","issue_comment_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/issues/comments{/number}","contents_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/contents/{+path}","compare_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/merges","archive_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/downloads","issues_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/issues{/number}","pulls_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/pulls{/number}","milestones_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/milestones{/number}","notifications_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/labels{/name}","releases_url":"https://api.github.com/repos/Xenapto/griddler-cloudmailin/releases{/id}","created_at":"2015-06-05T17:28:04Z","updated_at":"2015-06-05T17:28:05Z","pushed_at":"2015-06-06T23:34:01Z","git_url":"git://github.com/Xenapto/griddler-cloudmailin.git","ssh_url":"git@github.com:Xenapto/griddler-cloudmailin.git","clone_url":"https://github.com/Xenapto/griddler-cloudmailin.git","svn_url":"https://github.com/Xenapto/griddler-cloudmailin","homepage":null,"size":86,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"thoughtbot:master","ref":"master","sha":"d032eacf703a92889d8c4358e968bf0d9a08311f","user":{"login":"thoughtbot","id":6183,"avatar_url":"https://avatars.githubusercontent.com/u/6183?v=3","gravatar_id":"","url":"https://api.github.com/users/thoughtbot","html_url":"https://github.com/thoughtbot","followers_url":"https://api.github.com/users/thoughtbot/followers","following_url":"https://api.github.com/users/thoughtbot/following{/other_user}","gists_url":"https://api.github.com/users/thoughtbot/gists{/gist_id}","starred_url":"https://api.github.com/users/thoughtbot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thoughtbot/subscriptions","organizations_url":"https://api.github.com/users/thoughtbot/orgs","repos_url":"https://api.github.com/users/thoughtbot/repos","events_url":"https://api.github.com/users/thoughtbot/events{/privacy}","received_events_url":"https://api.github.com/users/thoughtbot/received_events","type":"Organization","site_admin":false},"repo":{"id":21004659,"name":"griddler-cloudmailin","full_name":"thoughtbot/griddler-cloudmailin","owner":{"login":"thoughtbot","id":6183,"avatar_url":"https://avatars.githubusercontent.com/u/6183?v=3","gravatar_id":"","url":"https://api.github.com/users/thoughtbot","html_url":"https://github.com/thoughtbot","followers_url":"https://api.github.com/users/thoughtbot/followers","following_url":"https://api.github.com/users/thoughtbot/following{/other_user}","gists_url":"https://api.github.com/users/thoughtbot/gists{/gist_id}","starred_url":"https://api.github.com/users/thoughtbot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/thoughtbot/subscriptions","organizations_url":"https://api.github.com/users/thoughtbot/orgs","repos_url":"https://api.github.com/users/thoughtbot/repos","events_url":"https://api.github.com/users/thoughtbot/events{/privacy}","received_events_url":"https://api.github.com/users/thoughtbot/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/thoughtbot/griddler-cloudmailin","description":"","fork":false,"url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin","forks_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/forks","keys_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/teams","hooks_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/hooks","issue_events_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/issues/events{/number}","events_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/events","assignees_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/assignees{/user}","branches_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/branches{/branch}","tags_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/tags","blobs_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/git/refs{/sha}","trees_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/statuses/{sha}","languages_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/languages","stargazers_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/stargazers","contributors_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/contributors","subscribers_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/subscribers","subscription_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/subscription","commits_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/commits{/sha}","git_commits_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/git/commits{/sha}","comments_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/comments{/number}","issue_comment_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/issues/comments{/number}","contents_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/contents/{+path}","compare_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/merges","archive_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/downloads","issues_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/issues{/number}","pulls_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls{/number}","milestones_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/milestones{/number}","notifications_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/labels{/name}","releases_url":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/releases{/id}","created_at":"2014-06-19T15:06:40Z","updated_at":"2014-06-19T17:28:11Z","pushed_at":"2015-06-06T23:34:01Z","git_url":"git://github.com/thoughtbot/griddler-cloudmailin.git","ssh_url":"git@github.com:thoughtbot/griddler-cloudmailin.git","clone_url":"https://github.com/thoughtbot/griddler-cloudmailin.git","svn_url":"https://github.com/thoughtbot/griddler-cloudmailin","homepage":null,"size":140,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":2,"forks":1,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls/3"},"html":{"href":"https://github.com/thoughtbot/griddler-cloudmailin/pull/3"},"issue":{"href":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/issues/3"},"comments":{"href":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/thoughtbot/griddler-cloudmailin/statuses/8ce0f6b0223e7b986a81a96511d512c479b12171"}},"merged":false,"mergeable":true,"mergeable_state":"clean","merged_by":null,"comments":2,"review_comments":22,"commits":3,"additions":79,"deletions":16,"changed_files":3}}