{"action":"created","comment":{"url":"https://api.github.com/repos/letsencrypt/boulder/pulls/comments/93129541","pull_request_review_id":13651760,"id":93129541,"diff_hunk":"@@ -98,9 +98,23 @@ func (m *mailer) sendNags(contacts []string, certs []*x509.Certificate) error {\n \t}\n \tdomains = core.UniqueLowerNames(domains)\n \tsort.Strings(domains)\n-\n \tm.log.Debug(fmt.Sprintf(\"Sending mail for %s (%s)\", strings.Join(domains, \", \"), strings.Join(serials, \", \")))\n \n+\tvar subject string\n+\tif m.subject != \"\" {\n+\t\t// If there is a subject from the configuration file, we should use it as-is\n+\t\t// to preserve the \"classic\" behaviour before we added a domain name.\n+\t\tsubject = m.subject\n+\t} else {\n+\t\t// Otherwise, when no subject is configured we should make one using the\n+\t\t// domain names in the expiring certificate\n+\t\tsubject = fmt.Sprintf(\"Certificate expiration notice for domain %q\", domains[0])\n+\t\tif len(domains) > 1 {\n+\t\t\tsubject += fmt.Sprintf(\" (and %d more)\", len(domains)-1)\n+\t\t}\n+\t}\n+\tm.log.Debug(fmt.Sprintf(\"Message subject %q\", subject))","path":"cmd/expiration-mailer/main.go","position":null,"original_position":20,"commit_id":"cacb1a4f5f969fb5c71c36c258fcaeef2466dcf6","original_commit_id":"db02d9b22274cbf4486af9e8c5a77ce52d51ca0e","user":{"login":"cpu","id":292650,"avatar_url":"https://avatars.githubusercontent.com/u/292650?v=3","gravatar_id":"","url":"https://api.github.com/users/cpu","html_url":"https://github.com/cpu","followers_url":"https://api.github.com/users/cpu/followers","following_url":"https://api.github.com/users/cpu/following{/other_user}","gists_url":"https://api.github.com/users/cpu/gists{/gist_id}","starred_url":"https://api.github.com/users/cpu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cpu/subscriptions","organizations_url":"https://api.github.com/users/cpu/orgs","repos_url":"https://api.github.com/users/cpu/repos","events_url":"https://api.github.com/users/cpu/events{/privacy}","received_events_url":"https://api.github.com/users/cpu/received_events","type":"User","site_admin":false},"body":"Agreed - fixed in https://github.com/letsencrypt/boulder/pull/2435/commits/cacb1a4f5f969fb5c71c36c258fcaeef2466dcf6","created_at":"2016-12-19T22:03:04Z","updated_at":"2016-12-19T22:03:04Z","html_url":"https://github.com/letsencrypt/boulder/pull/2435#discussion_r93129541","pull_request_url":"https://api.github.com/repos/letsencrypt/boulder/pulls/2435","_links":{"self":{"href":"https://api.github.com/repos/letsencrypt/boulder/pulls/comments/93129541"},"html":{"href":"https://github.com/letsencrypt/boulder/pull/2435#discussion_r93129541"},"pull_request":{"href":"https://api.github.com/repos/letsencrypt/boulder/pulls/2435"}}},"pull_request":{"url":"https://api.github.com/repos/letsencrypt/boulder/pulls/2435","id":98366396,"html_url":"https://github.com/letsencrypt/boulder/pull/2435","diff_url":"https://github.com/letsencrypt/boulder/pull/2435.diff","patch_url":"https://github.com/letsencrypt/boulder/pull/2435.patch","issue_url":"https://api.github.com/repos/letsencrypt/boulder/issues/2435","number":2435,"state":"open","locked":false,"title":"Include domain name in email subj","user":{"login":"cpu","id":292650,"avatar_url":"https://avatars.githubusercontent.com/u/292650?v=3","gravatar_id":"","url":"https://api.github.com/users/cpu","html_url":"https://github.com/cpu","followers_url":"https://api.github.com/users/cpu/followers","following_url":"https://api.github.com/users/cpu/following{/other_user}","gists_url":"https://api.github.com/users/cpu/gists{/gist_id}","starred_url":"https://api.github.com/users/cpu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cpu/subscriptions","organizations_url":"https://api.github.com/users/cpu/orgs","repos_url":"https://api.github.com/users/cpu/repos","events_url":"https://api.github.com/users/cpu/events{/privacy}","received_events_url":"https://api.github.com/users/cpu/received_events","type":"User","site_admin":false},"body":"This PR modifies the `expiration-mailer` utility to change the subject used in the reminder emails to include a domain name from the expiring certificate.\r\n\r\nPreviously unless otherwise specified using the `Mailer.Subject` configuration parameter all reminder emails were sent with the subject `Certificate expiration notice`. Both the `test/config/` and `test/config-next` expiration mailer configurations do not override the subject and were using the default.\r\n\r\nWith this PR, if no `Mailer.Subject` configuration parameter is provided then reminder emails are sent with the subject `Certificate expiration notice for domain \"foo.bar.com\"` in the case of only one domain in the expiring certificate, and `Certificate expiration for domain \"foo.bar.com\" (and $(n-1) more)` for the case where there are n > 1 domains (e.g. \"(and 1 more)\", \"(and 2 more)\" ...). I explicitly left support for the `Mailer.Subject` override to allow legacy configurations to function.\r\n\r\nI didn't explicitly add a new unit test for this behaviour because the existing unit tests were exercising both the \"configuration override\" portion of the subject behaviour, and matching the new expected subject. It would be entirely duplicated code to write a separate test for the subject template.\r\n\r\nResolves #2411","created_at":"2016-12-16T16:47:17Z","updated_at":"2016-12-19T22:03:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"169fc05b6d19519d83f3d913ce3a146f13377be2","assignee":{"login":"cpu","id":292650,"avatar_url":"https://avatars.githubusercontent.com/u/292650?v=3","gravatar_id":"","url":"https://api.github.com/users/cpu","html_url":"https://github.com/cpu","followers_url":"https://api.github.com/users/cpu/followers","following_url":"https://api.github.com/users/cpu/following{/other_user}","gists_url":"https://api.github.com/users/cpu/gists{/gist_id}","starred_url":"https://api.github.com/users/cpu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cpu/subscriptions","organizations_url":"https://api.github.com/users/cpu/orgs","repos_url":"https://api.github.com/users/cpu/repos","events_url":"https://api.github.com/users/cpu/events{/privacy}","received_events_url":"https://api.github.com/users/cpu/received_events","type":"User","site_admin":false},"assignees":[{"login":"cpu","id":292650,"avatar_url":"https://avatars.githubusercontent.com/u/292650?v=3","gravatar_id":"","url":"https://api.github.com/users/cpu","html_url":"https://github.com/cpu","followers_url":"https://api.github.com/users/cpu/followers","following_url":"https://api.github.com/users/cpu/following{/other_user}","gists_url":"https://api.github.com/users/cpu/gists{/gist_id}","starred_url":"https://api.github.com/users/cpu/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cpu/subscriptions","organizations_url":"https://api.github.com/users/cpu/orgs","repos_url":"https://api.github.com/users/cpu/repos","events_url":"https://api.github.com/users/cpu/events{/privacy}","received_events_url":"https://api.github.com/users/cpu/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/letsencrypt/boulder/pulls/2435/commits","review_comments_url":"https://api.github.com/repos/letsencrypt/boulder/pulls/2435/comments","review_comment_url":"https://api.github.com/repos/letsencrypt/boulder/pulls/comments{/number}","comments_url":"https://api.github.com/repos/letsencrypt/boulder/issues/2435/comments","statuses_url":"https://api.github.com/repos/letsencrypt/boulder/statuses/cacb1a4f5f969fb5c71c36c258fcaeef2466dcf6","head":{"label":"letsencrypt:cpu-expiry-reminder-you-may-have-already-won","ref":"cpu-expiry-reminder-you-may-have-already-won","sha":"cacb1a4f5f969fb5c71c36c258fcaeef2466dcf6","user":{"login":"letsencrypt","id":9289019,"avatar_url":"https://avatars.githubusercontent.com/u/9289019?v=3","gravatar_id":"","url":"https://api.github.com/users/letsencrypt","html_url":"https://github.com/letsencrypt","followers_url":"https://api.github.com/users/letsencrypt/followers","following_url":"https://api.github.com/users/letsencrypt/following{/other_user}","gists_url":"https://api.github.com/users/letsencrypt/gists{/gist_id}","starred_url":"https://api.github.com/users/letsencrypt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/letsencrypt/subscriptions","organizations_url":"https://api.github.com/users/letsencrypt/orgs","repos_url":"https://api.github.com/users/letsencrypt/repos","events_url":"https://api.github.com/users/letsencrypt/events{/privacy}","received_events_url":"https://api.github.com/users/letsencrypt/received_events","type":"Organization","site_admin":false},"repo":{"id":28283593,"name":"boulder","full_name":"letsencrypt/boulder","owner":{"login":"letsencrypt","id":9289019,"avatar_url":"https://avatars.githubusercontent.com/u/9289019?v=3","gravatar_id":"","url":"https://api.github.com/users/letsencrypt","html_url":"https://github.com/letsencrypt","followers_url":"https://api.github.com/users/letsencrypt/followers","following_url":"https://api.github.com/users/letsencrypt/following{/other_user}","gists_url":"https://api.github.com/users/letsencrypt/gists{/gist_id}","starred_url":"https://api.github.com/users/letsencrypt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/letsencrypt/subscriptions","organizations_url":"https://api.github.com/users/letsencrypt/orgs","repos_url":"https://api.github.com/users/letsencrypt/repos","events_url":"https://api.github.com/users/letsencrypt/events{/privacy}","received_events_url":"https://api.github.com/users/letsencrypt/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/letsencrypt/boulder","description":"An ACME-based CA, written in Go.","fork":false,"url":"https://api.github.com/repos/letsencrypt/boulder","forks_url":"https://api.github.com/repos/letsencrypt/boulder/forks","keys_url":"https://api.github.com/repos/letsencrypt/boulder/keys{/key_id}","collaborators_url":"https://api.github.com/repos/letsencrypt/boulder/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/letsencrypt/boulder/teams","hooks_url":"https://api.github.com/repos/letsencrypt/boulder/hooks","issue_events_url":"https://api.github.com/repos/letsencrypt/boulder/issues/events{/number}","events_url":"https://api.github.com/repos/letsencrypt/boulder/events","assignees_url":"https://api.github.com/repos/letsencrypt/boulder/assignees{/user}","branches_url":"https://api.github.com/repos/letsencrypt/boulder/branches{/branch}","tags_url":"https://api.github.com/repos/letsencrypt/boulder/tags","blobs_url":"https://api.github.com/repos/letsencrypt/boulder/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/letsencrypt/boulder/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/letsencrypt/boulder/git/refs{/sha}","trees_url":"https://api.github.com/repos/letsencrypt/boulder/git/trees{/sha}","statuses_url":"https://api.github.com/repos/letsencrypt/boulder/statuses/{sha}","languages_url":"https://api.github.com/repos/letsencrypt/boulder/languages","stargazers_url":"https://api.github.com/repos/letsencrypt/boulder/stargazers","contributors_url":"https://api.github.com/repos/letsencrypt/boulder/contributors","subscribers_url":"https://api.github.com/repos/letsencrypt/boulder/subscribers","subscription_url":"https://api.github.com/repos/letsencrypt/boulder/subscription","commits_url":"https://api.github.com/repos/letsencrypt/boulder/commits{/sha}","git_commits_url":"https://api.github.com/repos/letsencrypt/boulder/git/commits{/sha}","comments_url":"https://api.github.com/repos/letsencrypt/boulder/comments{/number}","issue_comment_url":"https://api.github.com/repos/letsencrypt/boulder/issues/comments{/number}","contents_url":"https://api.github.com/repos/letsencrypt/boulder/contents/{+path}","compare_url":"https://api.github.com/repos/letsencrypt/boulder/compare/{base}...{head}","merges_url":"https://api.github.com/repos/letsencrypt/boulder/merges","archive_url":"https://api.github.com/repos/letsencrypt/boulder/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/letsencrypt/boulder/downloads","issues_url":"https://api.github.com/repos/letsencrypt/boulder/issues{/number}","pulls_url":"https://api.github.com/repos/letsencrypt/boulder/pulls{/number}","milestones_url":"https://api.github.com/repos/letsencrypt/boulder/milestones{/number}","notifications_url":"https://api.github.com/repos/letsencrypt/boulder/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/letsencrypt/boulder/labels{/name}","releases_url":"https://api.github.com/repos/letsencrypt/boulder/releases{/id}","deployments_url":"https://api.github.com/repos/letsencrypt/boulder/deployments","created_at":"2014-12-21T00:29:54Z","updated_at":"2016-12-19T14:06:21Z","pushed_at":"2016-12-19T22:02:46Z","git_url":"git://github.com/letsencrypt/boulder.git","ssh_url":"git@github.com:letsencrypt/boulder.git","clone_url":"https://github.com/letsencrypt/boulder.git","svn_url":"https://github.com/letsencrypt/boulder","homepage":null,"size":22777,"stargazers_count":1589,"watchers_count":1589,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":195,"mirror_url":null,"open_issues_count":169,"forks":195,"open_issues":169,"watchers":1589,"default_branch":"master"}},"base":{"label":"letsencrypt:master","ref":"master","sha":"0cc0ab9d9b1e72f7f094ee3a3a3e2a2f4ff88442","user":{"login":"letsencrypt","id":9289019,"avatar_url":"https://avatars.githubusercontent.com/u/9289019?v=3","gravatar_id":"","url":"https://api.github.com/users/letsencrypt","html_url":"https://github.com/letsencrypt","followers_url":"https://api.github.com/users/letsencrypt/followers","following_url":"https://api.github.com/users/letsencrypt/following{/other_user}","gists_url":"https://api.github.com/users/letsencrypt/gists{/gist_id}","starred_url":"https://api.github.com/users/letsencrypt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/letsencrypt/subscriptions","organizations_url":"https://api.github.com/users/letsencrypt/orgs","repos_url":"https://api.github.com/users/letsencrypt/repos","events_url":"https://api.github.com/users/letsencrypt/events{/privacy}","received_events_url":"https://api.github.com/users/letsencrypt/received_events","type":"Organization","site_admin":false},"repo":{"id":28283593,"name":"boulder","full_name":"letsencrypt/boulder","owner":{"login":"letsencrypt","id":9289019,"avatar_url":"https://avatars.githubusercontent.com/u/9289019?v=3","gravatar_id":"","url":"https://api.github.com/users/letsencrypt","html_url":"https://github.com/letsencrypt","followers_url":"https://api.github.com/users/letsencrypt/followers","following_url":"https://api.github.com/users/letsencrypt/following{/other_user}","gists_url":"https://api.github.com/users/letsencrypt/gists{/gist_id}","starred_url":"https://api.github.com/users/letsencrypt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/letsencrypt/subscriptions","organizations_url":"https://api.github.com/users/letsencrypt/orgs","repos_url":"https://api.github.com/users/letsencrypt/repos","events_url":"https://api.github.com/users/letsencrypt/events{/privacy}","received_events_url":"https://api.github.com/users/letsencrypt/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/letsencrypt/boulder","description":"An ACME-based CA, written in Go.","fork":false,"url":"https://api.github.com/repos/letsencrypt/boulder","forks_url":"https://api.github.com/repos/letsencrypt/boulder/forks","keys_url":"https://api.github.com/repos/letsencrypt/boulder/keys{/key_id}","collaborators_url":"https://api.github.com/repos/letsencrypt/boulder/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/letsencrypt/boulder/teams","hooks_url":"https://api.github.com/repos/letsencrypt/boulder/hooks","issue_events_url":"https://api.github.com/repos/letsencrypt/boulder/issues/events{/number}","events_url":"https://api.github.com/repos/letsencrypt/boulder/events","assignees_url":"https://api.github.com/repos/letsencrypt/boulder/assignees{/user}","branches_url":"https://api.github.com/repos/letsencrypt/boulder/branches{/branch}","tags_url":"https://api.github.com/repos/letsencrypt/boulder/tags","blobs_url":"https://api.github.com/repos/letsencrypt/boulder/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/letsencrypt/boulder/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/letsencrypt/boulder/git/refs{/sha}","trees_url":"https://api.github.com/repos/letsencrypt/boulder/git/trees{/sha}","statuses_url":"https://api.github.com/repos/letsencrypt/boulder/statuses/{sha}","languages_url":"https://api.github.com/repos/letsencrypt/boulder/languages","stargazers_url":"https://api.github.com/repos/letsencrypt/boulder/stargazers","contributors_url":"https://api.github.com/repos/letsencrypt/boulder/contributors","subscribers_url":"https://api.github.com/repos/letsencrypt/boulder/subscribers","subscription_url":"https://api.github.com/repos/letsencrypt/boulder/subscription","commits_url":"https://api.github.com/repos/letsencrypt/boulder/commits{/sha}","git_commits_url":"https://api.github.com/repos/letsencrypt/boulder/git/commits{/sha}","comments_url":"https://api.github.com/repos/letsencrypt/boulder/comments{/number}","issue_comment_url":"https://api.github.com/repos/letsencrypt/boulder/issues/comments{/number}","contents_url":"https://api.github.com/repos/letsencrypt/boulder/contents/{+path}","compare_url":"https://api.github.com/repos/letsencrypt/boulder/compare/{base}...{head}","merges_url":"https://api.github.com/repos/letsencrypt/boulder/merges","archive_url":"https://api.github.com/repos/letsencrypt/boulder/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/letsencrypt/boulder/downloads","issues_url":"https://api.github.com/repos/letsencrypt/boulder/issues{/number}","pulls_url":"https://api.github.com/repos/letsencrypt/boulder/pulls{/number}","milestones_url":"https://api.github.com/repos/letsencrypt/boulder/milestones{/number}","notifications_url":"https://api.github.com/repos/letsencrypt/boulder/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/letsencrypt/boulder/labels{/name}","releases_url":"https://api.github.com/repos/letsencrypt/boulder/releases{/id}","deployments_url":"https://api.github.com/repos/letsencrypt/boulder/deployments","created_at":"2014-12-21T00:29:54Z","updated_at":"2016-12-19T14:06:21Z","pushed_at":"2016-12-19T22:02:46Z","git_url":"git://github.com/letsencrypt/boulder.git","ssh_url":"git@github.com:letsencrypt/boulder.git","clone_url":"https://github.com/letsencrypt/boulder.git","svn_url":"https://github.com/letsencrypt/boulder","homepage":null,"size":22777,"stargazers_count":1589,"watchers_count":1589,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":195,"mirror_url":null,"open_issues_count":169,"forks":195,"open_issues":169,"watchers":1589,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/letsencrypt/boulder/pulls/2435"},"html":{"href":"https://github.com/letsencrypt/boulder/pull/2435"},"issue":{"href":"https://api.github.com/repos/letsencrypt/boulder/issues/2435"},"comments":{"href":"https://api.github.com/repos/letsencrypt/boulder/issues/2435/comments"},"review_comments":{"href":"https://api.github.com/repos/letsencrypt/boulder/pulls/2435/comments"},"review_comment":{"href":"https://api.github.com/repos/letsencrypt/boulder/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/letsencrypt/boulder/pulls/2435/commits"},"statuses":{"href":"https://api.github.com/repos/letsencrypt/boulder/statuses/cacb1a4f5f969fb5c71c36c258fcaeef2466dcf6"}}}}
{"actor":{"display_login":"cpu"}}