fix(email): encode Cyrillic binaries with /utf8.
OTP truncates non-ASCII in <<"...">> to 8-bit bytes, garbling Russian in mail and in-app notification copy.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
-export([render/2, render_reminder/3, render_waitlist_promoted/2]).
|
||||
|
||||
%% Kind: verify | invite | reset
|
||||
%% Non-ASCII binaries MUST use /utf8 (OTP truncates codepoints to 8 bits otherwise).
|
||||
-spec render(verify | invite | reset, binary()) ->
|
||||
{Subject :: binary(), Plain :: binary(), Html :: binary()}.
|
||||
render(Kind, Url) ->
|
||||
@@ -12,28 +13,28 @@ render(Kind, Url) ->
|
||||
-spec render_reminder(binary(), binary(), binary()) ->
|
||||
{Subject :: binary(), Plain :: binary(), Html :: binary()}.
|
||||
render_reminder(Url, Title, WhenText) ->
|
||||
Subject = <<"CalenTIQ: напоминание о записи">>,
|
||||
Heading = <<"Напоминание о записи">>,
|
||||
Subject = <<"CalenTIQ: напоминание о записи"/utf8>>,
|
||||
Heading = <<"Напоминание о записи"/utf8>>,
|
||||
Lead = iolist_to_binary([
|
||||
<<"Скоро: «">>, Title, <<"» — ">>, WhenText, <<" (UTC).">>
|
||||
<<"Скоро: «"/utf8>>, Title, <<"» — "/utf8>>, WhenText, <<" (UTC).">>
|
||||
]),
|
||||
Cta = <<"Открыть запись">>,
|
||||
Foot = <<"Вы получили письмо, потому что записаны на это событие в CalenTIQ.">>,
|
||||
Pre = <<"Напоминание о записи в CalenTIQ">>,
|
||||
Cta = <<"Открыть запись"/utf8>>,
|
||||
Foot = <<"Вы получили письмо, потому что записаны на это событие в CalenTIQ."/utf8>>,
|
||||
Pre = <<"Напоминание о записи в CalenTIQ"/utf8>>,
|
||||
assemble(Subject, Heading, Lead, Url, Cta, Foot, Pre).
|
||||
|
||||
-spec render_waitlist_promoted(binary(), binary()) ->
|
||||
{Subject :: binary(), Plain :: binary(), Html :: binary()}.
|
||||
render_waitlist_promoted(Url, Title) ->
|
||||
Subject = <<"CalenTIQ: место в листе ожидания">>,
|
||||
Heading = <<"Для вас освободилось место">>,
|
||||
Subject = <<"CalenTIQ: место в листе ожидания"/utf8>>,
|
||||
Heading = <<"Для вас освободилось место"/utf8>>,
|
||||
Lead = iolist_to_binary([
|
||||
<<"Вы были в листе ожидания на «">>, Title,
|
||||
<<"». Мы записали вас — откройте событие в CalenTIQ.">>
|
||||
<<"Вы были в листе ожидания на «"/utf8>>, Title,
|
||||
<<"». Мы записали вас — откройте событие в CalenTIQ."/utf8>>
|
||||
]),
|
||||
Cta = <<"Открыть событие">>,
|
||||
Foot = <<"Если запись вам не нужна, отмените её в приложении.">>,
|
||||
Pre = <<"Место из листа ожидания CalenTIQ">>,
|
||||
Cta = <<"Открыть событие"/utf8>>,
|
||||
Foot = <<"Если запись вам не нужна, отмените её в приложении."/utf8>>,
|
||||
Pre = <<"Место из листа ожидания CalenTIQ"/utf8>>,
|
||||
assemble(Subject, Heading, Lead, Url, Cta, Foot, Pre).
|
||||
|
||||
assemble(Subject, Heading, Lead, Url, Cta, Foot, Pre) ->
|
||||
@@ -49,26 +50,26 @@ assemble(Subject, Heading, Lead, Url, Cta, Foot, Pre) ->
|
||||
{Subject, Plain, Html}.
|
||||
|
||||
copy(verify) ->
|
||||
{<<"CalenTIQ: подтвердите email">>,
|
||||
<<"Подтвердите email">>,
|
||||
<<"Один календарь. Три режима для вашего времени. Нажмите кнопку, чтобы активировать аккаунт.">>,
|
||||
<<"Подтвердить email">>,
|
||||
<<"Если вы не регистрировались в CalenTIQ, просто проигнорируйте письмо.">>,
|
||||
<<"Подтвердите email в CalenTIQ">>};
|
||||
{<<"CalenTIQ: подтвердите email"/utf8>>,
|
||||
<<"Подтвердите email"/utf8>>,
|
||||
<<"Один календарь. Три режима для вашего времени. Нажмите кнопку, чтобы активировать аккаунт."/utf8>>,
|
||||
<<"Подтвердить email"/utf8>>,
|
||||
<<"Если вы не регистрировались в CalenTIQ, просто проигнорируйте письмо."/utf8>>,
|
||||
<<"Подтвердите email в CalenTIQ"/utf8>>};
|
||||
copy(invite) ->
|
||||
{<<"CalenTIQ: приглашение специалиста">>,
|
||||
<<"Вас пригласили как специалиста">>,
|
||||
<<"Откройте приглашение, чтобы принять или отклонить его в CalenTIQ.">>,
|
||||
<<"Открыть приглашение">>,
|
||||
<<"Письмо отправлено, потому что владелец календаря указал этот адрес.">>,
|
||||
<<"Приглашение специалиста в CalenTIQ">>};
|
||||
{<<"CalenTIQ: приглашение специалиста"/utf8>>,
|
||||
<<"Вас пригласили как специалиста"/utf8>>,
|
||||
<<"Откройте приглашение, чтобы принять или отклонить его в CalenTIQ."/utf8>>,
|
||||
<<"Открыть приглашение"/utf8>>,
|
||||
<<"Письмо отправлено, потому что владелец календаря указал этот адрес."/utf8>>,
|
||||
<<"Приглашение специалиста в CalenTIQ"/utf8>>};
|
||||
copy(reset) ->
|
||||
{<<"CalenTIQ: сброс пароля">>,
|
||||
<<"Сброс пароля">>,
|
||||
<<"Если это были вы — задайте новый пароль по кнопке. Ссылка одноразовая.">>,
|
||||
<<"Сменить пароль">>,
|
||||
<<"Если вы не запрашивали сброс, проигнорируйте письмо — пароль не изменится.">>,
|
||||
<<"Сброс пароля CalenTIQ">>}.
|
||||
{<<"CalenTIQ: сброс пароля"/utf8>>,
|
||||
<<"Сброс пароля"/utf8>>,
|
||||
<<"Если это были вы — задайте новый пароль по кнопке. Ссылка одноразовая."/utf8>>,
|
||||
<<"Сменить пароль"/utf8>>,
|
||||
<<"Если вы не запрашивали сброс, проигнорируйте письмо — пароль не изменится."/utf8>>,
|
||||
<<"Сброс пароля CalenTIQ"/utf8>>}.
|
||||
|
||||
layout() ->
|
||||
case read_priv() of
|
||||
|
||||
@@ -49,14 +49,14 @@ notify_specialist_invite(UserId, Invite) ->
|
||||
|
||||
%% In-app / WS: напоминание о записи (Back#70)
|
||||
notify_event_reminder(UserId, #{title := Title, when_text := WhenText} = Data) ->
|
||||
NTitle = <<"Напоминание о записи">>,
|
||||
Body = iolist_to_binary([<<"Скоро: «">>, Title, <<"» — ">>, WhenText, <<" (UTC)">>]),
|
||||
NTitle = <<"Напоминание о записи"/utf8>>,
|
||||
Body = iolist_to_binary([<<"Скоро: «"/utf8>>, Title, <<"» — "/utf8>>, WhenText, <<" (UTC)">>]),
|
||||
_ = core_notification:create(UserId, event_reminder, NTitle, Body),
|
||||
broadcast_to_user(UserId, event_reminder, Data#{user_id => UserId}).
|
||||
|
||||
notify_waitlist_promoted(UserId, #{title := Title} = Data) ->
|
||||
NTitle = <<"Место из листа ожидания">>,
|
||||
Body = iolist_to_binary([<<"Вас записали на «">>, Title, <<"».">>]),
|
||||
NTitle = <<"Место из листа ожидания"/utf8>>,
|
||||
Body = iolist_to_binary([<<"Вас записали на «"/utf8>>, Title, <<"»."/utf8>>]),
|
||||
_ = core_notification:create(UserId, waitlist_promoted, NTitle, Body),
|
||||
broadcast_to_user(UserId, waitlist_promoted, Data#{user_id => UserId}).
|
||||
|
||||
|
||||
@@ -187,8 +187,8 @@ do_create(OwnerId, CalendarId, UserId, Email, Opts) ->
|
||||
|
||||
notify_invite(#specialist_invite{invitee_user_id = UserId, calendar_id = CalId,
|
||||
token = Token} = Inv) when UserId =/= <<>> ->
|
||||
Title = <<"Приглашение стать специалистом">>,
|
||||
Body = <<"Вас пригласили в календарь ", CalId/binary>>,
|
||||
Title = <<"Приглашение стать специалистом"/utf8>>,
|
||||
Body = <<"Вас пригласили в календарь "/utf8, CalId/binary>>,
|
||||
_ = core_notification:create(UserId, specialist_invite, Title, Body),
|
||||
logic_notification:notify_specialist_invite(UserId, Inv),
|
||||
maybe_email(Inv, Token);
|
||||
|
||||
Reference in New Issue
Block a user