From 295af311870c21cb18fae320a15879dde5c79c19 Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Fri, 13 Dec 2024 22:24:08 -0500 Subject: [PATCH] Revert "Remove Circular ingestion from legacy email" --- .../circulars/__tests__/parse.ts | 37 +++++++++++++++++-- app/email-incoming/circulars/index.ts | 6 +-- app/email-incoming/circulars/parse.ts | 35 +++++++++++++++++- app/routes/docs.circulars.submitting.mdx | 9 ++++- app/routes/docs.contributing.email/route.mdx | 6 ++- 5 files changed, 83 insertions(+), 10 deletions(-) diff --git a/app/email-incoming/circulars/__tests__/parse.ts b/app/email-incoming/circulars/__tests__/parse.ts index 1434a9a98..9e77a93a0 100644 --- a/app/email-incoming/circulars/__tests__/parse.ts +++ b/app/email-incoming/circulars/__tests__/parse.ts @@ -39,10 +39,41 @@ describe('getFromAddress', () => { ).toThrow('From address is missing') }) + test("raises if the from address name does not contain ' via '", () => { + expect(() => + getFromAddress( + parseFrom( + '"Example " ' + ) + ) + ).toThrow("Expected From name to contain ' via '") + }) + test('returns the address verbatim for a normal email address', () => { - expect(getFromAddress(parseFrom('example@example.com'))).toEqual( - 'example@example.com' - ) + expect(getFromAddress(parseFrom('example@example.com'))).toEqual({ + address: 'example@example.com', + submittedHow: 'email', + }) + }) + + test('returns the original address for a rewritten address', () => { + expect( + getFromAddress( + parseFrom( + '"Example via gcncirc" ' + ) + ) + ).toEqual({ address: 'example@example.com', submittedHow: 'email-legacy' }) + }) + + test('returns the original address for a rewritten address with an alternative "via" name', () => { + expect( + getFromAddress( + parseFrom( + '"Example via my mind" ' + ) + ) + ).toEqual({ address: 'example@example.com', submittedHow: 'email-legacy' }) }) }) diff --git a/app/email-incoming/circulars/index.ts b/app/email-incoming/circulars/index.ts index 8c620fa6e..61f637e2f 100644 --- a/app/email-incoming/circulars/index.ts +++ b/app/email-incoming/circulars/index.ts @@ -53,7 +53,7 @@ const fromName = 'GCN Circulars' export const handler = createEmailIncomingMessageHandler( async ({ content }) => { const parsed = await parseEmailContentFromSource(content) - const userEmail = getFromAddress(parsed.from) + const { address: userEmail, submittedHow } = getFromAddress(parsed.from) const to = getReplyToAddresses(parsed.replyTo) ?? [userEmail] const userData = @@ -92,7 +92,7 @@ export const handler = createEmailIncomingMessageHandler( body: parsed.text, sub: userData.sub, submitter: formatAuthor(userData), - submittedHow: 'email', + submittedHow, } const eventId = parseEventFromSubject(parsed.subject) @@ -204,7 +204,7 @@ If you have not already done so, we encourage you to make an account at ${origin - Your Circulars settings have been transferred automatically. - You are able to submit Circulars from the same email addresses registered in the legacy service. - Emails from GCN come from a new address, no-reply@${hostname}. -- We encourage you to submit Circulars to the new address, circulars@${hostname}. The old address, gcncirc@capella2.gsfc.nasa.gov, has been retired. +- We encourage you to submit Circulars to the new address, circulars@${hostname}. The old GCN Circulars submission address, gcncirc@capella2.gsfc.nasa.gov, will be retired on December 31, 2024. - The new archive, ${origin}/circulars, includes all past Circulars. We have frozen the old archive, https://gcn.gsfc.nasa.gov/gcn3_archive.html. For more information about the GCN Circulars, please see ${origin}/circulars. diff --git a/app/email-incoming/circulars/parse.ts b/app/email-incoming/circulars/parse.ts index 3b3582003..e1aa43cc6 100644 --- a/app/email-incoming/circulars/parse.ts +++ b/app/email-incoming/circulars/parse.ts @@ -7,12 +7,43 @@ */ import type { AddressObject, Source } from 'mailparser' import { simpleParser } from 'mailparser' +import addressparser from 'nodemailer/lib/addressparser' +import type { SubmittedHow } from '~/routes/circulars/circulars.lib' + +const legacyAddress = 'mailnull@capella2.gsfc.nasa.gov' +const legacyFromNameSplitter = ' via ' + +/** + * Parse rewritten From addresses from capella2. + * + * Messages forwarded by capella2 from non-NASA addresses have From headers + * that are rewritten like this: + * + * From: Albert Einstein + * --rewritten to-- + * From: "Albert Einstein via gcncirc" + * + */ export function getFromAddress(fromAddressObject?: AddressObject) { - const from = fromAddressObject?.value[0] + let from = fromAddressObject?.value[0] + let submittedHow: SubmittedHow + if (from?.address === legacyAddress) { + const i = from.name.lastIndexOf(legacyFromNameSplitter) + if (i === -1) + throw new Error( + `Expected From name to contain '${legacyFromNameSplitter}'` + ) + from = addressparser(from.name.slice(0, i), { + flatten: true, + })[0] + submittedHow = 'email-legacy' + } else { + submittedHow = 'email' + } const address = from?.address if (!address) throw new Error('From address is missing') - return address + return { address, submittedHow } } export function getReplyToAddresses(replyTo?: AddressObject) { diff --git a/app/routes/docs.circulars.submitting.mdx b/app/routes/docs.circulars.submitting.mdx index 2f2527723..233e0e32a 100644 --- a/app/routes/docs.circulars.submitting.mdx +++ b/app/routes/docs.circulars.submitting.mdx @@ -71,4 +71,11 @@ To post a GCN Circular via the web form, simply go to the [GCN Circulars archive ### Post a GCN Circular by Email -To submit a GCN Circular by email, send a message to . +To submit a GCN Circular by email, send a message to: . + +The legacy address gcncirc@capella2.gsfc.nasa.gov forwards emails to . This forwarding will be retired on December 31, 2024. Note that the new address is stricter than the old address about the `From:` address matching the sender. + + + **Do not send your Circular to both email addresses.** If you send it to both + addresses, then it will be distributed twice as two different circulars. + diff --git a/app/routes/docs.contributing.email/route.mdx b/app/routes/docs.contributing.email/route.mdx index f26c87d78..26ce61ed9 100644 --- a/app/routes/docs.contributing.email/route.mdx +++ b/app/routes/docs.contributing.email/route.mdx @@ -20,7 +20,7 @@ Note that each flow chart represents the email processing for a single one of GC Flow chart of GCN Circulars ingestion -Authorized GCN users can [submit GCN Circulars](/docs/circulars/submitting) in either of two ways: by logging in and completing the [Web form](/circulars/new) or by submitting an email to circulars@stage.gcn.nasa.gov. +Authorized GCN users can [submit GCN Circulars](/docs/circulars/submitting) in any one of three ways: by logging in and completing the [Web form](/circulars/new), by submitting an email to circulars@stage.gcn.nasa.gov, or by submitting an email to the legacy GCN Classic server at gcncirc@capella2.gsfc.nasa.gov. ### By Web form @@ -36,6 +36,10 @@ To submit a Circular via email, the user sends an email to circulars@stagegcncirc@capella2.gsfc.nasa.gov + +The legacy, on-premise GCN Classic server at NASA Goddard Space Flight Center, capella2.gsfc.nasa.gov, is configured to forward messages addressed to gcncirc@capella2.gsfc.nasa.gov to circulars@gcn.nasa.gov. Once received by Amazon SES, processing proceeds the same as above. + ## Support Requests **Source code:** [app/email-incoming/support](https://github.com/nasa-gcn/gcn.nasa.gov/tree/main/app/email-incoming/support)