feat(email): system/user senderType + attachments
Composer validator now takes senderType (system|user) and an attachments[] array, and the service dispatches across two paths: the system path uses lib/email/index.ts with port-config noreply identity and logs signed_doc_emailed when an attachment matches a document's signed PDF; the user path stays on the existing personal- account flow but is gated by the new email.allowPersonalAccountSends toggle and the attachment fileIds are persisted on email_messages. sendEmail in lib/email accepts attachments and resolves them from MinIO with cross-port enforcement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ export const SETTING_KEYS = {
|
||||
emailReplyTo: 'email_reply_to',
|
||||
emailSignatureHtml: 'email_signature_html',
|
||||
emailFooterHtml: 'email_footer_html',
|
||||
emailAllowPersonalAccountSends: 'email_allow_personal_account_sends',
|
||||
smtpHostOverride: 'smtp_host_override',
|
||||
smtpPortOverride: 'smtp_port_override',
|
||||
smtpUserOverride: 'smtp_user_override',
|
||||
@@ -66,6 +67,12 @@ export interface PortEmailConfig {
|
||||
smtpPort: number;
|
||||
smtpUser: string | null;
|
||||
smtpPass: string | null;
|
||||
/**
|
||||
* When false, only the system (port-config) sender identity is allowed.
|
||||
* When true, admins/users may send via their connected personal email
|
||||
* account. Defaults to false for safety.
|
||||
*/
|
||||
allowPersonalAccountSends: boolean;
|
||||
}
|
||||
|
||||
export async function getPortEmailConfig(portId: string): Promise<PortEmailConfig> {
|
||||
@@ -79,6 +86,7 @@ export async function getPortEmailConfig(portId: string): Promise<PortEmailConfi
|
||||
smtpPort,
|
||||
smtpUser,
|
||||
smtpPass,
|
||||
allowPersonalAccountSends,
|
||||
] = await Promise.all([
|
||||
readSetting<string>(SETTING_KEYS.emailFromName, portId),
|
||||
readSetting<string>(SETTING_KEYS.emailFromAddress, portId),
|
||||
@@ -89,6 +97,7 @@ export async function getPortEmailConfig(portId: string): Promise<PortEmailConfi
|
||||
readSetting<number>(SETTING_KEYS.smtpPortOverride, portId),
|
||||
readSetting<string>(SETTING_KEYS.smtpUserOverride, portId),
|
||||
readSetting<string>(SETTING_KEYS.smtpPassOverride, portId),
|
||||
readSetting<boolean>(SETTING_KEYS.emailAllowPersonalAccountSends, portId),
|
||||
]);
|
||||
|
||||
// Parse env.SMTP_FROM into name + address if no port override
|
||||
@@ -114,6 +123,7 @@ export async function getPortEmailConfig(portId: string): Promise<PortEmailConfi
|
||||
smtpPort: smtpPort ?? env.SMTP_PORT,
|
||||
smtpUser: smtpUser ?? env.SMTP_USER ?? null,
|
||||
smtpPass: smtpPass ?? env.SMTP_PASS ?? null,
|
||||
allowPersonalAccountSends: allowPersonalAccountSends ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user