mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-06 00:15:32 +00:00
fix: check a meeting reply's sender against the attendee who answers, not the organizer
This commit is contained in:
@@ -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(<CalendarInvitationBanner email={replyFrom('email-14', 'alice@example.com')} />);
|
||||
await waitFor(() => expect(screen.getByRole('heading', { name: 'Sync' })).toBeInTheDocument());
|
||||
expect(screen.queryByText(/was sent from/)).toBeNull();
|
||||
unmount();
|
||||
|
||||
render(<CalendarInvitationBanner email={replyFrom('email-15', 'mallory@evil.example')} />);
|
||||
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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<CalendarEvent> = {
|
||||
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.
|
||||
|
||||
+18
-13
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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": "بحاجة إلى رد",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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ěď",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "نیاز به پاسخ",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "צריך תגובה",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "返答が必要です",
|
||||
|
||||
@@ -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": "응답이 필요해요",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "Хариулт хэрэгтэй",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "Требуется ответ",
|
||||
|
||||
@@ -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ď",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "Потребує відповіді",
|
||||
|
||||
@@ -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": "待回覆",
|
||||
|
||||
@@ -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": "待回复",
|
||||
|
||||
Reference in New Issue
Block a user