From f0392a670570f491f065d597aee6fcaae9b77569 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Mon, 26 Oct 2026 14:27:52 +0100 Subject: [PATCH] fix: check a meeting reply's sender against the attendee who answers, not the organizer --- .../calendar-invitation-banner.test.tsx | 27 ++++++++++++++++ .../email/calendar-invitation-banner.tsx | 10 ++++++ lib/__tests__/calendar-invitation.test.ts | 22 +++++++++++++ lib/calendar-invitation.ts | 31 +++++++++++-------- locales/ar/common.json | 2 ++ locales/ca/common.json | 2 ++ locales/cs/common.json | 2 ++ locales/da/common.json | 2 ++ locales/de/common.json | 2 ++ locales/en/common.json | 2 ++ locales/es/common.json | 2 ++ locales/et/common.json | 2 ++ locales/fa/common.json | 2 ++ locales/fr/common.json | 2 ++ locales/he/common.json | 2 ++ locales/hu/common.json | 2 ++ locales/it/common.json | 2 ++ locales/ja/common.json | 2 ++ locales/ko/common.json | 2 ++ locales/lv/common.json | 2 ++ locales/mn/common.json | 2 ++ locales/nb/common.json | 2 ++ locales/nl/common.json | 2 ++ locales/pl/common.json | 2 ++ locales/pt/common.json | 2 ++ locales/ro/common.json | 2 ++ locales/ru/common.json | 2 ++ locales/sk/common.json | 2 ++ locales/tr/common.json | 2 ++ locales/uk/common.json | 2 ++ locales/zh-TW/common.json | 2 ++ locales/zh/common.json | 2 ++ 32 files changed, 133 insertions(+), 13 deletions(-) diff --git a/components/email/__tests__/calendar-invitation-banner.test.tsx b/components/email/__tests__/calendar-invitation-banner.test.tsx index 036eba6df..41672acdd 100644 --- a/components/email/__tests__/calendar-invitation-banner.test.tsx +++ b/components/email/__tests__/calendar-invitation-banner.test.tsx @@ -97,6 +97,7 @@ vi.mock('next-intl', () => ({ actor_note: 'Note: {comment}', actor_unknown: 'Someone', sender_mismatch_unverified_info: 'This invitation was sent from {sender}, while the organizer listed in the calendar data is {organizer}, and the message could not be verified.', + attendee_mismatch_unverified_info: 'This response was sent from {sender}, while the attendee answering in the calendar data is {attendee}, and the message could not be verified.', action_failed: 'Could not complete that calendar action.', proposal_applied: 'Proposed changes applied.', proposed_changes: 'Proposed changes', @@ -890,6 +891,32 @@ describe('CalendarInvitationBanner', () => { expect(mocks.calendarState.updateEvent).not.toHaveBeenCalled(); }); + it("checks a reply's sender against the attendee who answers, not the organizer", async () => { + const reply = { + uid: 'uid-14', title: 'Sync', start: '2026-03-27T09:00:00Z', duration: 'PT1H', + organizerCalendarAddress: 'mailto:user@example.com', + participants: { + a: { '@type': 'Participant', calendarAddress: 'mailto:user@example.com', roles: { owner: true, attendee: true }, participationStatus: 'accepted' }, + b: { '@type': 'Participant', calendarAddress: 'mailto:alice@example.com', roles: { attendee: true }, participationStatus: 'accepted' }, + }, + }; + mocks.clientMock.parseCalendarEvents.mockResolvedValue([reply]); + const replyFrom = (id: string, from: string) => makeEmail({ + id, from: [{ email: from }], + attachments: [{ partId: '1', blobId: `blob-${id}`, size: 256, type: 'text/calendar; method=REPLY', name: 'reply.ics' }], + }); + + const { unmount } = render(); + await waitFor(() => expect(screen.getByRole('heading', { name: 'Sync' })).toBeInTheDocument()); + expect(screen.queryByText(/was sent from/)).toBeNull(); + unmount(); + + render(); + await waitFor(() => expect(screen.getByText( + 'This response was sent from mallory@evil.example, while the attendee answering in the calendar data is alice@example.com, and the message could not be verified.', + )).toBeInTheDocument()); + }); + it('lets a proposal from an attendee Stalwart lists by calendar address be applied', async () => { mocks.calendarState.updateEvent = vi.fn().mockResolvedValue(true); // As 0.16 and 1.0 store and parse them: mailto: calendar addresses, no email. diff --git a/components/email/calendar-invitation-banner.tsx b/components/email/calendar-invitation-banner.tsx index 0ba4b332f..a002851c0 100644 --- a/components/email/calendar-invitation-banner.tsx +++ b/components/email/calendar-invitation-banner.tsx @@ -155,6 +155,16 @@ function getTrustMessage( sender: trustAssessment.senderEmail ?? '', organizer: trustAssessment.organizerEmail ?? '', }); + case 'attendee_mismatch': + return t('attendee_mismatch_info', { + sender: trustAssessment.senderEmail ?? '', + attendee: trustAssessment.attendeeEmail ?? '', + }); + case 'attendee_mismatch_unverified': + return t('attendee_mismatch_unverified_info', { + sender: trustAssessment.senderEmail ?? '', + attendee: trustAssessment.attendeeEmail ?? '', + }); default: return null; } diff --git a/lib/__tests__/calendar-invitation.test.ts b/lib/__tests__/calendar-invitation.test.ts index 12b268fbc..d033a69db 100644 --- a/lib/__tests__/calendar-invitation.test.ts +++ b/lib/__tests__/calendar-invitation.test.ts @@ -478,6 +478,28 @@ describe('getInvitationTrustAssessment', () => { expect(result.reason).toBeNull(); }); + // A reply comes from the attendee, and the organizer is the user reading + // it: comparing with the organizer warned on every genuine reply, and a + // forged one looked just the same. + it.each(['reply', 'counter', 'refresh'] as const)('compares the sender of a %s with the attendee who answers', (method) => { + const event: Partial = { + participants: { + // As Stalwart parses it: the organizer is an attendee too, addresses as mailto:. + org: makeParticipant({ roles: { owner: true, attendee: true }, email: undefined, calendarAddress: 'mailto:me@example.com', participationStatus: 'accepted' }), + bob: makeParticipant({ roles: { attendee: true }, email: undefined, calendarAddress: 'mailto:Bob@example.net', participationStatus: 'accepted' }), + }, + }; + const aligned = { dkim: { result: 'pass', domain: 'example.net', selector: 's' } } as const; + + const genuine = getInvitationTrustAssessment(event, makeEmail({ from: [{ email: 'bob@example.net' }], authenticationResults: aligned }), method); + expect(genuine.level).toBe('trusted'); + + const forged = getInvitationTrustAssessment(event, makeEmail({ from: [{ email: 'mallory@evil.example' }] }), method); + expect(forged).toMatchObject({ + level: 'warning', reason: 'attendee_mismatch_unverified', senderEmail: 'mallory@evil.example', attendeeEmail: 'bob@example.net', + }); + }); + it('does not trust an SPF or DKIM pass for a domain other than the From domain', () => { // MAIL FROM at the attacker's domain (SPF pass there), From and ORGANIZER // at the victim's; the victim publishes no DMARC policy, so dmarc=none. diff --git a/lib/calendar-invitation.ts b/lib/calendar-invitation.ts index 2ff7a22ea..ab95bdf51 100644 --- a/lib/calendar-invitation.ts +++ b/lib/calendar-invitation.ts @@ -21,9 +21,13 @@ export interface InvitationTrustAssessment { | 'authentication_missing' | 'sender_mismatch' | 'sender_mismatch_unverified' + | 'attendee_mismatch' + | 'attendee_mismatch_unverified' | null; senderEmail: string | null; organizerEmail: string | null; + /** The attendee who answers in a reply, counter or refresh. */ + attendeeEmail: string | null; } export interface InvitationActorSummary { @@ -399,17 +403,22 @@ export function getInvitationTrustAssessment( ): InvitationTrustAssessment { const organizerEmail = getOrganizerEmail(event); const senderEmail = getPrimaryAddressEmail(email?.from) || getPrimaryAddressEmail(email?.replyTo); + // A reply, counter or refresh is sent by the attendee who answers; the + // organizer is usually the user reading it. + const fromAttendee = method === 'reply' || method === 'counter' || method === 'refresh'; + const attendeeEmail = fromAttendee ? getInvitationActorSummary(event, method)?.email ?? null : null; + const expectedEmail = fromAttendee ? attendeeEmail : organizerEmail; const verifiedAuthentication = hasVerifiedAuthentication(email); const authenticationFailure = hasAuthenticationFailure(email); - const senderMismatch = Boolean(senderEmail && organizerEmail && senderEmail !== organizerEmail); + const senderMismatch = Boolean(senderEmail && expectedEmail && senderEmail !== expectedEmail); const expectsAuthenticatedTransport = method !== 'unknown'; + const addresses = { senderEmail, organizerEmail, attendeeEmail }; if (senderMismatch && (authenticationFailure || !verifiedAuthentication)) { return { level: 'warning', - reason: 'sender_mismatch_unverified', - senderEmail, - organizerEmail, + reason: fromAttendee ? 'attendee_mismatch_unverified' : 'sender_mismatch_unverified', + ...addresses, }; } @@ -417,17 +426,15 @@ export function getInvitationTrustAssessment( return { level: 'warning', reason: 'authentication_failed', - senderEmail, - organizerEmail, + ...addresses, }; } if (senderMismatch) { return { level: 'caution', - reason: 'sender_mismatch', - senderEmail, - organizerEmail, + reason: fromAttendee ? 'attendee_mismatch' : 'sender_mismatch', + ...addresses, }; } @@ -435,16 +442,14 @@ export function getInvitationTrustAssessment( return { level: 'caution', reason: 'authentication_missing', - senderEmail, - organizerEmail, + ...addresses, }; } return { level: 'trusted', reason: null, - senderEmail, - organizerEmail, + ...addresses, }; } diff --git a/locales/ar/common.json b/locales/ar/common.json index 9e71b7d94..35b26f728 100644 --- a/locales/ar/common.json +++ b/locales/ar/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "لا تتضمن هذه الدعوة مصادقة بريد موثّقة. تأكد من التفاصيل مع المنظّم إذا بدا أي شيء غير معتاد.", "sender_mismatch_info": "أُرسلت هذه الدعوة من {sender}، بينما المنظّم المدرج في بيانات التقويم هو {organizer}.", "sender_mismatch_unverified_info": "أُرسلت هذه الدعوة من {sender}، بينما المنظّم المدرج في بيانات التقويم هو {organizer}، ولم يتم التحقق من الرسالة.", + "attendee_mismatch_info": "أُرسل هذا الرد من {sender}، بينما الحاضر المجيب في بيانات التقويم هو {attendee}.", + "attendee_mismatch_unverified_info": "أُرسل هذا الرد من {sender}، بينما الحاضر المجيب في بيانات التقويم هو {attendee}، ولم يتم التحقق من الرسالة.", "organizer_role": "أنت منظّم هذا الحدث", "your_response": "ردّك: {status}", "response_needed": "بحاجة إلى رد", diff --git a/locales/ca/common.json b/locales/ca/common.json index ea9fe96ff..ec2b94af8 100644 --- a/locales/ca/common.json +++ b/locales/ca/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "Aquesta invitació no inclou autenticació de correu verificada. Confirmeu els detalls amb l'organitzador si alguna cosa sembla estranya.", "sender_mismatch_info": "Aquesta invitació s'ha enviat des de {sender}, mentre que l'organitzador indicat a les dades del calendari és {organizer}.", "sender_mismatch_unverified_info": "Aquesta invitació s'ha enviat des de {sender}, mentre que l'organitzador indicat a les dades del calendari és {organizer}, i no s'ha pogut verificar el missatge.", + "attendee_mismatch_info": "Aquesta resposta s'ha enviat des de {sender}, mentre que l'assistent que respon a les dades del calendari és {attendee}.", + "attendee_mismatch_unverified_info": "Aquesta resposta s'ha enviat des de {sender}, mentre que l'assistent que respon a les dades del calendari és {attendee}, i no s'ha pogut verificar el missatge.", "organizer_role": "Vós organitzeu aquest esdeveniment", "your_response": "La vostra resposta: {status}", "response_needed": "Cal resposta", diff --git a/locales/cs/common.json b/locales/cs/common.json index df339741b..5101b52f7 100644 --- a/locales/cs/common.json +++ b/locales/cs/common.json @@ -542,6 +542,8 @@ "authentication_missing_info": "Tato pozvánka neobsahuje ověření zprávy. Pokud se vám cokoli zdá neobvyklé, potvrďte si podrobnosti s organizátorem.", "sender_mismatch_info": "Tato pozvánka byla odeslána od {sender}, zatímco organizátor v datech kalendáře je {organizer}.", "sender_mismatch_unverified_info": "Tato pozvánka byla odeslána od {sender}, zatímco organizátor v datech kalendáře je {organizer}, a zprávu se nepodařilo ověřit.", + "attendee_mismatch_info": "Tato odpověď byla odeslána od {sender}, zatímco odpovídající účastník v datech kalendáře je {attendee}.", + "attendee_mismatch_unverified_info": "Tato odpověď byla odeslána od {sender}, zatímco odpovídající účastník v datech kalendáře je {attendee}, a zprávu se nepodařilo ověřit.", "organizer_role": "Jste organizátorem této události", "your_response": "Vaše odpověď: {status}", "response_needed": "Vyžaduje odpověď", diff --git a/locales/da/common.json b/locales/da/common.json index 00fe3b0f9..dadb5b8e5 100644 --- a/locales/da/common.json +++ b/locales/da/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "Denne invitation inkluderer ikke bekræftet mailgodkendelse. Bekræft detaljerne med organisatoren, hvis noget ser usædvanligt ud.", "sender_mismatch_info": "Denne invitation blev sendt fra {sender}, mens organisatoren i kalenderdataene er {organizer}.", "sender_mismatch_unverified_info": "Denne invitation blev sendt fra {sender}, mens organisatoren i kalenderdataene er {organizer}, og beskeden kunne ikke bekræftes.", + "attendee_mismatch_info": "Dette svar blev sendt fra {sender}, mens deltageren, der svarer i kalenderdataene, er {attendee}.", + "attendee_mismatch_unverified_info": "Dette svar blev sendt fra {sender}, mens deltageren, der svarer i kalenderdataene, er {attendee}, og beskeden kunne ikke bekræftes.", "organizer_role": "Du organiserer denne begivenhed", "your_response": "Dit svar: {status}", "response_needed": "Kræver svar", diff --git a/locales/de/common.json b/locales/de/common.json index 3fe99327e..216751562 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -540,6 +540,8 @@ "authentication_missing_info": "Diese Einladung enthält keine verifizierte Mail-Authentifizierung. Bestätigen Sie die Details mit dem Organisator, wenn etwas ungewöhnlich wirkt.", "sender_mismatch_info": "Diese Einladung wurde von {sender} gesendet, während der in den Kalenderdaten angegebene Organisator {organizer} ist.", "sender_mismatch_unverified_info": "Diese Einladung wurde von {sender} gesendet, während der in den Kalenderdaten angegebene Organisator {organizer} ist, und die Nachricht konnte nicht verifiziert werden.", + "attendee_mismatch_info": "Diese Antwort wurde von {sender} gesendet, während der antwortende Teilnehmer in den Kalenderdaten {attendee} ist.", + "attendee_mismatch_unverified_info": "Diese Antwort wurde von {sender} gesendet, während der antwortende Teilnehmer in den Kalenderdaten {attendee} ist, und die Nachricht konnte nicht verifiziert werden.", "organizer_role": "Sie organisieren dieses Ereignis", "your_response": "Ihre Antwort: {status}", "response_needed": "Antwort ausstehend", diff --git a/locales/en/common.json b/locales/en/common.json index b9d547a9c..f2bf8ecdd 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "This invitation does not include verified mail authentication. Confirm the details with the organizer if anything looks unusual.", "sender_mismatch_info": "This invitation was sent from {sender}, while the organizer listed in the calendar data is {organizer}.", "sender_mismatch_unverified_info": "This invitation was sent from {sender}, while the organizer listed in the calendar data is {organizer}, and the message could not be verified.", + "attendee_mismatch_info": "This response was sent from {sender}, while the attendee answering in the calendar data is {attendee}.", + "attendee_mismatch_unverified_info": "This response was sent from {sender}, while the attendee answering in the calendar data is {attendee}, and the message could not be verified.", "organizer_role": "You organize this event", "your_response": "Your response: {status}", "response_needed": "Needs response", diff --git a/locales/es/common.json b/locales/es/common.json index 305b43674..37b41a8e8 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -540,6 +540,8 @@ "authentication_missing_info": "Esta invitación no incluye autenticación de correo verificada. Confirma los detalles con el organizador si algo parece inusual.", "sender_mismatch_info": "Esta invitación se envió desde {sender}, mientras que el organizador indicado en los datos del calendario es {organizer}.", "sender_mismatch_unverified_info": "Esta invitación se envió desde {sender}, mientras que el organizador indicado en los datos del calendario es {organizer}, y el mensaje no pudo verificarse.", + "attendee_mismatch_info": "Esta respuesta se envió desde {sender}, mientras que el asistente que responde en los datos del calendario es {attendee}.", + "attendee_mismatch_unverified_info": "Esta respuesta se envió desde {sender}, mientras que el asistente que responde en los datos del calendario es {attendee}, y el mensaje no pudo verificarse.", "organizer_role": "Organizas este evento", "your_response": "Tu respuesta: {status}", "response_needed": "Pendiente de respuesta", diff --git a/locales/et/common.json b/locales/et/common.json index c6253c0c7..7be101509 100644 --- a/locales/et/common.json +++ b/locales/et/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "Sellel kutsel puudub kinnitatud e-posti autentimine. Kui midagi tundub kahtlane, kontrolli üksikasju korraldajaga.", "sender_mismatch_info": "See kutse saadeti aadressilt {sender}, kuid kalendriandmetes märgitud korraldaja on {organizer}.", "sender_mismatch_unverified_info": "See kutse saadeti aadressilt {sender}, kuid kalendriandmetes märgitud korraldaja on {organizer}, ning kirja ei õnnestunud kinnitada.", + "attendee_mismatch_info": "See vastus saadeti aadressilt {sender}, kuid kalendriandmetes vastav osaleja on {attendee}.", + "attendee_mismatch_unverified_info": "See vastus saadeti aadressilt {sender}, kuid kalendriandmetes vastav osaleja on {attendee}, ning kirja ei õnnestunud kinnitada.", "organizer_role": "Sina oled selle sündmuse korraldaja", "your_response": "Sinu vastus: {status}", "response_needed": "Vajab vastust", diff --git a/locales/fa/common.json b/locales/fa/common.json index 15f0843c5..f06930529 100644 --- a/locales/fa/common.json +++ b/locales/fa/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "این دعوت‌نامه فاقد احراز هویت ایمیل است.", "sender_mismatch_info": "این دعوت‌نامه از {sender} ارسال شده ولی برگزارکننده {organizer} است.", "sender_mismatch_unverified_info": "از {sender} ارسال شده ولی برگزارکننده {organizer} است و پیام تأیید نشد.", + "attendee_mismatch_info": "این پاسخ از {sender} ارسال شده ولی شرکت‌کننده‌ی پاسخ‌دهنده {attendee} است.", + "attendee_mismatch_unverified_info": "این پاسخ از {sender} ارسال شده ولی شرکت‌کننده‌ی پاسخ‌دهنده {attendee} است و پیام تأیید نشد.", "organizer_role": "شما برگزارکننده این رویداد هستید", "your_response": "پاسخ شما: {status}", "response_needed": "نیاز به پاسخ", diff --git a/locales/fr/common.json b/locales/fr/common.json index 0bd1ee8b6..54fc124d8 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -540,6 +540,8 @@ "authentication_missing_info": "Cette invitation ne comporte pas d'authentification de messagerie vérifiée. Vérifiez les détails avec l'organisateur si quelque chose semble inhabituel.", "sender_mismatch_info": "Cette invitation a été envoyée depuis {sender}, alors que l'organisateur indiqué dans les données du calendrier est {organizer}.", "sender_mismatch_unverified_info": "Cette invitation a été envoyée depuis {sender}, alors que l'organisateur indiqué dans les données du calendrier est {organizer}, et le message n'a pas pu être vérifié.", + "attendee_mismatch_info": "Cette réponse a été envoyée depuis {sender}, alors que le participant qui répond dans les données du calendrier est {attendee}.", + "attendee_mismatch_unverified_info": "Cette réponse a été envoyée depuis {sender}, alors que le participant qui répond dans les données du calendrier est {attendee}, et le message n'a pas pu être vérifié.", "organizer_role": "Vous organisez cet événement", "your_response": "Votre réponse : {status}", "response_needed": "Réponse requise", diff --git a/locales/he/common.json b/locales/he/common.json index f7323b901..0f9ee1090 100644 --- a/locales/he/common.json +++ b/locales/he/common.json @@ -488,6 +488,8 @@ "authentication_missing_info": "הזמנה זו אינה כוללת אימות דואר מאומת. אשר את הפרטים עם המארגן אם משהו נראה חריג.", "sender_mismatch_info": "הזמנה זו נשלחה מ-{sender}, בעוד שהמארגן הרשום בנתוני היומן הוא{organizer}.", "sender_mismatch_unverified_info": "הזמנה זו נשלחה מ-{sender}, בעוד שהמארגן הרשום בנתוני היומן הוא{organizer}, ולא ניתן לאמת את ההודעה.", + "attendee_mismatch_info": "תגובה זו נשלחה מ-{sender}, בעוד שהמשתתף המשיב בנתוני היומן הוא {attendee}.", + "attendee_mismatch_unverified_info": "תגובה זו נשלחה מ-{sender}, בעוד שהמשתתף המשיב בנתוני היומן הוא {attendee}, ולא ניתן לאמת את ההודעה.", "organizer_role": "אתה מארגן את האירוע הזה", "your_response": "תגובתך:{status}", "response_needed": "צריך תגובה", diff --git a/locales/hu/common.json b/locales/hu/common.json index aa004a92e..29d372a2b 100644 --- a/locales/hu/common.json +++ b/locales/hu/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "Ez a meghívó nem tartalmaz ellenőrzött e-mail hitelesítést. Ha bármi szokatlannak tűnik, erősítsd meg a részleteket a szervezővel.", "sender_mismatch_info": "Ezt a meghívót {sender} küldte, míg a naptár adatokban szereplő szervező {organizer}.", "sender_mismatch_unverified_info": "Ezt a meghívót {sender} küldte, míg a naptár adatokban szereplő szervező {organizer}, és az üzenet nem volt hitelesíthető.", + "attendee_mismatch_info": "Ezt a választ {sender} küldte, míg a naptár adatokban válaszoló résztvevő {attendee}.", + "attendee_mismatch_unverified_info": "Ezt a választ {sender} küldte, míg a naptár adatokban válaszoló résztvevő {attendee}, és az üzenet nem volt hitelesíthető.", "organizer_role": "Te szervezed ezt az eseményt", "your_response": "Válaszod: {status}", "response_needed": "Válasz szükséges", diff --git a/locales/it/common.json b/locales/it/common.json index 528d5f530..733a7f3c4 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -540,6 +540,8 @@ "authentication_missing_info": "Questo invito non include un'autenticazione email verificata. Conferma i dettagli con l'organizzatore se qualcosa sembra insolito.", "sender_mismatch_info": "Questo invito è stato inviato da {sender}, mentre l'organizzatore indicato nei dati del calendario è {organizer}.", "sender_mismatch_unverified_info": "Questo invito è stato inviato da {sender}, mentre l'organizzatore indicato nei dati del calendario è {organizer}, e il messaggio non ha potuto essere verificato.", + "attendee_mismatch_info": "Questa risposta è stata inviata da {sender}, mentre il partecipante che risponde nei dati del calendario è {attendee}.", + "attendee_mismatch_unverified_info": "Questa risposta è stata inviata da {sender}, mentre il partecipante che risponde nei dati del calendario è {attendee}, e il messaggio non ha potuto essere verificato.", "organizer_role": "Sei l'organizzatore di questo evento", "your_response": "La tua risposta: {status}", "response_needed": "Risposta richiesta", diff --git a/locales/ja/common.json b/locales/ja/common.json index 0d90ce2aa..250372613 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -540,6 +540,8 @@ "authentication_missing_info": "この招待には検証済みのメール認証がありません。不審な点があれば主催者に詳細を確認してください。", "sender_mismatch_info": "この招待は {sender} から送信されましたが、カレンダーデータ上の主催者は {organizer} です。", "sender_mismatch_unverified_info": "この招待は {sender} から送信されましたが、カレンダーデータ上の主催者は {organizer} であり、メッセージも検証できませんでした。", + "attendee_mismatch_info": "この返信は {sender} から送信されましたが、カレンダーデータ上で返信している参加者は {attendee} です。", + "attendee_mismatch_unverified_info": "この返信は {sender} から送信されましたが、カレンダーデータ上で返信している参加者は {attendee} であり、メッセージも検証できませんでした。", "organizer_role": "あなたがこのイベントの主催者です", "your_response": "あなたの返答: {status}", "response_needed": "返答が必要です", diff --git a/locales/ko/common.json b/locales/ko/common.json index 2f9f59c95..52b10e67d 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -542,6 +542,8 @@ "authentication_missing_info": "이 초대장에는 확인된 메일 인증 정보가 없어요. 이상한 점이 있다면 주최자에게 확인해 보세요.", "sender_mismatch_info": "초대장은 {sender}님이 보냈지만, 캘린더에 등록된 주최자는 {organizer}님이에요.", "sender_mismatch_unverified_info": "초대장은 {sender}님이 보냈지만 캘린더의 주최자는 {organizer}님이며, 메시지를 검증할 수 없어요.", + "attendee_mismatch_info": "이 응답은 {sender}님이 보냈지만 캘린더에서 응답한 참석자는 {attendee}님이에요.", + "attendee_mismatch_unverified_info": "이 응답은 {sender}님이 보냈지만 캘린더에서 응답한 참석자는 {attendee}님이며, 메시지를 검증할 수 없어요.", "organizer_role": "내가 주최하는 일정이에요", "your_response": "내 응답: {status}", "response_needed": "응답이 필요해요", diff --git a/locales/lv/common.json b/locales/lv/common.json index 8784a9859..65dcff2c9 100644 --- a/locales/lv/common.json +++ b/locales/lv/common.json @@ -542,6 +542,8 @@ "authentication_missing_info": "Šim uzaicinājumam nav apstiprinātas autentifikācijas.", "sender_mismatch_info": "Uzaicinājumu nosūtīja {sender}, bet organizators ir {organizer}.", "sender_mismatch_unverified_info": "Uzaicinājumu nosūtīja {sender}, bet norādītais organizators ir {organizer}, un ziņojumu nevarēja pārbaudīt.", + "attendee_mismatch_info": "Atbildi nosūtīja {sender}, bet atbildošais dalībnieks ir {attendee}.", + "attendee_mismatch_unverified_info": "Atbildi nosūtīja {sender}, bet atbildošais dalībnieks ir {attendee}, un ziņojumu nevarēja pārbaudīt.", "organizer_role": "Jūs esat šī pasākuma organizators", "your_response": "Jūsu atbilde: {status}", "response_needed": "Nepieciešama atbilde", diff --git a/locales/mn/common.json b/locales/mn/common.json index 9bd741777..565ce6cda 100644 --- a/locales/mn/common.json +++ b/locales/mn/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "Энэ урилгад баталгаажуулсан имэйлийн баталгаажуулалт ороогүй болно. Ер бусын зүйл байвал зохион байгуулагчтай дэлгэрэнгүй мэдээллийг баталгаажуулна уу.", "sender_mismatch_info": "Энэ урилгыг {sender}-с илгээсэн бол хуанлийн өгөгдөлд жагсаасан зохион байгуулагч нь {organizer} байна.", "sender_mismatch_unverified_info": "Энэ урилгыг {sender}-с илгээсэн бөгөөд хуанлийн өгөгдөлд жагсаасан зохион байгуулагч нь {organizer} бөгөөд мессежийг баталгаажуулж чадсангүй.", + "attendee_mismatch_info": "Энэ хариуг {sender}-с илгээсэн бөгөөд хуанлийн өгөгдөлд хариулж буй оролцогч нь {attendee}.", + "attendee_mismatch_unverified_info": "Энэ хариуг {sender}-с илгээсэн бөгөөд хуанлийн өгөгдөлд хариулж буй оролцогч нь {attendee} бөгөөд мессежийг баталгаажуулж чадсангүй.", "organizer_role": "Та энэ арга хэмжээг зохион байгуулна", "your_response": "Таны хариулт: {status}", "response_needed": "Хариулт хэрэгтэй", diff --git a/locales/nb/common.json b/locales/nb/common.json index a5800c956..bc7fa2837 100644 --- a/locales/nb/common.json +++ b/locales/nb/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "Denne invitasjonen har ingen bekreftet e-postautentisering. Avklar detaljene med arrangøren hvis noe ser uvanlig ut.", "sender_mismatch_info": "Denne invitasjonen ble sendt fra {sender}, mens arrangøren som er oppført i kalenderdataene er {organizer}.", "sender_mismatch_unverified_info": "Denne invitasjonen ble sendt fra {sender}, mens arrangøren som er oppført i kalenderdataene er {organizer}, og meldingen kunne ikke bekreftes.", + "attendee_mismatch_info": "Dette svaret ble sendt fra {sender}, mens deltakeren som svarer i kalenderdataene er {attendee}.", + "attendee_mismatch_unverified_info": "Dette svaret ble sendt fra {sender}, mens deltakeren som svarer i kalenderdataene er {attendee}, og meldingen kunne ikke bekreftes.", "organizer_role": "Du er arrangør for denne hendelsen", "your_response": "Ditt svar: {status}", "response_needed": "Svar kreves", diff --git a/locales/nl/common.json b/locales/nl/common.json index a48711b70..66344bf22 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -540,6 +540,8 @@ "authentication_missing_info": "Deze uitnodiging bevat geen geverifieerde mailauthenticatie. Controleer de details bij de organisator als iets ongewoon lijkt.", "sender_mismatch_info": "Deze uitnodiging is verzonden vanaf {sender}, terwijl de organisator in de kalendergegevens {organizer} is.", "sender_mismatch_unverified_info": "Deze uitnodiging is verzonden vanaf {sender}, terwijl de organisator in de kalendergegevens {organizer} is, en het bericht kon niet worden geverifieerd.", + "attendee_mismatch_info": "Dit antwoord is verzonden vanaf {sender}, terwijl de antwoordende deelnemer in de kalendergegevens {attendee} is.", + "attendee_mismatch_unverified_info": "Dit antwoord is verzonden vanaf {sender}, terwijl de antwoordende deelnemer in de kalendergegevens {attendee} is, en het bericht kon niet worden geverifieerd.", "organizer_role": "U organiseert dit evenement", "your_response": "Uw reactie: {status}", "response_needed": "Reactie vereist", diff --git a/locales/pl/common.json b/locales/pl/common.json index 296afebe8..70de9c21b 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -542,6 +542,8 @@ "authentication_missing_info": "To zaproszenie nie zawiera zweryfikowanego uwierzytelniania poczty. Potwierdź szczegóły z organizatorem, jeśli cokolwiek wygląda nietypowo.", "sender_mismatch_info": "To zaproszenie zostało wysłane z {sender}, podczas gdy organizator w danych kalendarza to {organizer}.", "sender_mismatch_unverified_info": "To zaproszenie zostało wysłane z {sender}, podczas gdy organizator w danych kalendarza to {organizer}, a wiadomość nie mogła zostać zweryfikowana.", + "attendee_mismatch_info": "Ta odpowiedź została wysłana z {sender}, podczas gdy odpowiadający uczestnik w danych kalendarza to {attendee}.", + "attendee_mismatch_unverified_info": "Ta odpowiedź została wysłana z {sender}, podczas gdy odpowiadający uczestnik w danych kalendarza to {attendee}, a wiadomość nie mogła zostać zweryfikowana.", "organizer_role": "Jesteś organizatorem tego wydarzenia", "your_response": "Twoja odpowiedź: {status}", "response_needed": "Wymaga odpowiedzi", diff --git a/locales/pt/common.json b/locales/pt/common.json index d624dcf1f..4cebf2fdb 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -540,6 +540,8 @@ "authentication_missing_info": "Este convite não inclui autenticação de email verificada. Confirme os detalhes com o organizador se algo parecer incomum.", "sender_mismatch_info": "Este convite foi enviado por {sender}, enquanto o organizador indicado nos dados do calendário é {organizer}.", "sender_mismatch_unverified_info": "Este convite foi enviado por {sender}, enquanto o organizador indicado nos dados do calendário é {organizer}, e a mensagem não pôde ser verificada.", + "attendee_mismatch_info": "Esta resposta foi enviada por {sender}, enquanto o participante que responde nos dados do calendário é {attendee}.", + "attendee_mismatch_unverified_info": "Esta resposta foi enviada por {sender}, enquanto o participante que responde nos dados do calendário é {attendee}, e a mensagem não pôde ser verificada.", "organizer_role": "Você organiza este evento", "your_response": "Sua resposta: {status}", "response_needed": "Resposta necessária", diff --git a/locales/ro/common.json b/locales/ro/common.json index e3390e866..97b650500 100644 --- a/locales/ro/common.json +++ b/locales/ro/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "Această invitație nu include autentificarea verificată a adresei de e-mail. Confirmați detaliile cu organizatorul dacă ceva pare neobișnuit.", "sender_mismatch_info": "Această invitație a fost trimisă de la {sender}, în timp ce organizatorul menționat în datele din calendar este {organizer}.", "sender_mismatch_unverified_info": "Această invitație a fost trimisă de la adresa {sender}, în timp ce organizatorul menționat în datele din calendar este {organizer}, iar mesajul nu a putut fi verificat.", + "attendee_mismatch_info": "Acest răspuns a fost trimis de la adresa {sender}, în timp ce participantul care răspunde în datele din calendar este {attendee}.", + "attendee_mismatch_unverified_info": "Acest răspuns a fost trimis de la adresa {sender}, în timp ce participantul care răspunde în datele din calendar este {attendee}, iar mesajul nu a putut fi verificat.", "organizer_role": "Tu organizezi acest eveniment", "your_response": "Răspunsul dvs.: {status}", "response_needed": "Necesită răspuns", diff --git a/locales/ru/common.json b/locales/ru/common.json index 1fa117545..0f08f8f1d 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -542,6 +542,8 @@ "authentication_missing_info": "Это приглашение не содержит подтверждённой аутентификации почты. Если что-то кажется необычным, уточните детали у организатора.", "sender_mismatch_info": "Это приглашение отправлено от {sender}, тогда как организатором в данных календаря указан {organizer}.", "sender_mismatch_unverified_info": "Это приглашение отправлено от {sender}, тогда как организатором указан {organizer}, и сообщение не удалось проверить.", + "attendee_mismatch_info": "Этот ответ отправлен от {sender}, тогда как отвечающим участником указан {attendee}.", + "attendee_mismatch_unverified_info": "Этот ответ отправлен от {sender}, тогда как отвечающим участником указан {attendee}, и сообщение не удалось проверить.", "organizer_role": "Вы являетесь организатором этого события", "your_response": "Ваш ответ: {status}", "response_needed": "Требуется ответ", diff --git a/locales/sk/common.json b/locales/sk/common.json index 090c74190..253b3eeff 100644 --- a/locales/sk/common.json +++ b/locales/sk/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "Táto pozvánka neobsahuje overené overenie správ. Potvrdte podrobnosti s organizátorom.", "sender_mismatch_info": "Táto pozvánka bola odoslaná od {sender}, zatiaľčo organizátor v dátach kalendára je {organizer}.", "sender_mismatch_unverified_info": "Táto pozvánka bola odoslaná od {sender}, zatiaľčo organizátor v dátach kalendára je {organizer}, a správu sa nepodarilo overiť.", + "attendee_mismatch_info": "Táto odpoveď bola odoslaná od {sender}, zatiaľ čo odpovedajúci účastník v dátach kalendára je {attendee}.", + "attendee_mismatch_unverified_info": "Táto odpoveď bola odoslaná od {sender}, zatiaľ čo odpovedajúci účastník v dátach kalendára je {attendee}, a správu sa nepodarilo overiť.", "organizer_role": "Ste organizátorom tejto udalosti", "your_response": "Vaša odpoveď: {status}", "response_needed": "Vyžaduje odpoveď", diff --git a/locales/tr/common.json b/locales/tr/common.json index b669457e3..ad5cbf2ca 100644 --- a/locales/tr/common.json +++ b/locales/tr/common.json @@ -542,6 +542,8 @@ "authentication_missing_info": "Bu davet doğrulanmış posta kimlik doğrulaması içermiyor. Bir şey olağandışı görünüyorsa ayrıntıları organizatörle teyit edin.", "sender_mismatch_info": "Bu davet {sender} tarafından gönderildi; ancak takvim verisinde organizatör olarak {organizer} listeleniyor.", "sender_mismatch_unverified_info": "Bu davet {sender} tarafından gönderildi; ancak takvim verisinde organizatör olarak {organizer} listeleniyor ve ileti doğrulanamadı.", + "attendee_mismatch_info": "Bu yanıt {sender} tarafından gönderildi; ancak takvim verisinde yanıtlayan katılımcı olarak {attendee} listeleniyor.", + "attendee_mismatch_unverified_info": "Bu yanıt {sender} tarafından gönderildi; ancak takvim verisinde yanıtlayan katılımcı olarak {attendee} listeleniyor ve ileti doğrulanamadı.", "organizer_role": "Bu etkinliği siz düzenliyorsunuz", "your_response": "Yanıtınız: {status}", "response_needed": "Yanıt gerekiyor", diff --git a/locales/uk/common.json b/locales/uk/common.json index 02bc6fffe..4782b754b 100644 --- a/locales/uk/common.json +++ b/locales/uk/common.json @@ -542,6 +542,8 @@ "authentication_missing_info": "Це запрошення не включає перевірену автентифікацію електронної пошти. Уточнюйте деталі в організатора, якщо щось виглядає незвичним.", "sender_mismatch_info": "Це запрошення надіслано з {sender}, а організатор, зазначений у даних календаря, {organizer}.", "sender_mismatch_unverified_info": "Це запрошення було надіслано з {sender}, а організатором, указаним у даних календаря, є {organizer}, і повідомлення не вдалося перевірити.", + "attendee_mismatch_info": "Цю відповідь було надіслано з {sender}, а учасником, який відповідає, у даних календаря є {attendee}.", + "attendee_mismatch_unverified_info": "Цю відповідь було надіслано з {sender}, а учасником, який відповідає, у даних календаря є {attendee}, і повідомлення не вдалося перевірити.", "organizer_role": "Ви організовуєте цю подію", "your_response": "Ваша відповідь: {status}", "response_needed": "Потребує відповіді", diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json index 865e600b2..42a78d48f 100644 --- a/locales/zh-TW/common.json +++ b/locales/zh-TW/common.json @@ -567,6 +567,8 @@ "authentication_missing_info": "這封邀請未包含已驗證的郵件身分驗證資訊。若有任何可疑之處,請向主辦人確認詳細資料。", "sender_mismatch_info": "這封邀請是由 {sender} 傳送,但行事曆資料中列出的主辦人是 {organizer}。", "sender_mismatch_unverified_info": "這封邀請是由 {sender} 傳送,但行事曆資料中列出的主辦人是 {organizer},而且無法驗證這封郵件。", + "attendee_mismatch_info": "這則回覆是由 {sender} 傳送,但行事曆資料中回覆的參與者是 {attendee}。", + "attendee_mismatch_unverified_info": "這則回覆是由 {sender} 傳送,但行事曆資料中回覆的參與者是 {attendee},而且無法驗證這封郵件。", "organizer_role": "您是此活動的主辦人", "your_response": "您的回覆:{status}", "response_needed": "待回覆", diff --git a/locales/zh/common.json b/locales/zh/common.json index fc53f5be2..e7bedf805 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -542,6 +542,8 @@ "authentication_missing_info": "此邀请不包括经过验证的邮件身份验证。如果有任何异常情况,请与组织者确认详细信息。", "sender_mismatch_info": "此邀请是从 {sender} 发送的,而日历数据中列出的组织者是 {organizer}。", "sender_mismatch_unverified_info": "此邀请是从 {sender} 发送的,而日历数据中列出的组织者是 {organizer},且无法验证该消息。", + "attendee_mismatch_info": "此回复是从 {sender} 发送的,而日历数据中作出回复的参与者是 {attendee}。", + "attendee_mismatch_unverified_info": "此回复是从 {sender} 发送的,而日历数据中作出回复的参与者是 {attendee},且无法验证该消息。", "organizer_role": "您是此活动的组织者", "your_response": "您的回复:{status}", "response_needed": "待回复",