bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch#include "lib.h"
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch#include "str.h"
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch#include "istream.h"
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch#include "strescape.h"
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch#include "array.h"
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch#include "time-util.h"
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch#include "hostpid.h"
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch#include "var-expand.h"
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch#include "ioloop.h"
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch#include "restrict-access.h"
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Bosch#include "anvil-client.h"
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch#include "settings-parser.h"
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch#include "mail-storage.h"
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch#include "mail-storage-service.h"
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch#include "mail-namespace.h"
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch#include "mail-deliver.h"
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch#include "mail-autoexpunge.h"
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch#include "index/raw/raw-storage.h"
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch#include "master-service.h"
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch#include "smtp-common.h"
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch#include "smtp-params.h"
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch#include "smtp-address.h"
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch#include "smtp-submit-settings.h"
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch#include "smtp-server.h"
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch#include "lda-settings.h"
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch#include "lmtp-settings.h"
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch#include "client.h"
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch#include "main.h"
c116e589182c258b463850327755e6dd9a731616Stephan Bosch#include "lmtp-common.h"
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch#include "lmtp-settings.h"
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch#include "lmtp-local.h"
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschstruct lmtp_local_recipient {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_recipient rcpt;
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch char *session_id;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch char *detail;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mail_storage_service_user *service_user;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct anvil_query *anvil_query;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch struct lmtp_local_recipient *duplicate;
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch bool anvil_connect_sent:1;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch};
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschstruct lmtp_local {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct client *client;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch ARRAY(struct lmtp_local_recipient *) rcpt_to;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mail *raw_mail, *first_saved_mail;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mail_user *rcpt_user;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch};
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschstatic void
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_rcpt_deinit(struct lmtp_local_recipient *rcpt);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch/*
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch * LMTP local
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch */
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschstatic struct lmtp_local *
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_init(struct client *client)
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch{
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local *local;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local = i_new(struct lmtp_local, 1);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local->client = client;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch i_array_init(&local->rcpt_to, 8);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch return local;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch}
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschvoid lmtp_local_deinit(struct lmtp_local **_local)
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch{
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local *local = *_local;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local_recipient *const *rcptp;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch *_local = NULL;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch if (array_is_created(&local->rcpt_to)) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch array_foreach_modifiable(&local->rcpt_to, rcptp)
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch lmtp_local_rcpt_deinit(*rcptp);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch array_free(&local->rcpt_to);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch }
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch if (local->raw_mail != NULL) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mailbox_transaction_context *raw_trans =
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local->raw_mail->transaction;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mailbox *raw_box = local->raw_mail->box;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch mail_free(&local->raw_mail);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch mailbox_transaction_rollback(&raw_trans);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch mailbox_free(&raw_box);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch }
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch i_free(local);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch}
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch/*
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch * Recipient
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch */
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Boschstatic void
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_rcpt_anvil_disconnect(struct lmtp_local_recipient *rcpt)
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch{
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch const struct mail_storage_service_input *input;
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch if (!rcpt->anvil_connect_sent)
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch return;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch rcpt->anvil_connect_sent = FALSE;
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch input = mail_storage_service_user_get_input(rcpt->service_user);
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch master_service_anvil_send(master_service, t_strconcat(
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch "DISCONNECT\t", my_pid, "\t", master_service_get_name(master_service),
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch "/", input->username, "\n", NULL));
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch}
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Boschstatic void
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Boschlmtp_local_rcpt_deinit(struct lmtp_local_recipient *rcpt)
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Bosch{
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Bosch if (rcpt->anvil_query != NULL)
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Bosch anvil_client_query_abort(anvil, &rcpt->anvil_query);
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Bosch lmtp_local_rcpt_anvil_disconnect(rcpt);
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Bosch mail_storage_service_user_unref(&rcpt->service_user);
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch i_free(rcpt->session_id);
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch i_free(rcpt->detail);
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch i_free(rcpt);
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Bosch}
70dfae6db8fd17ed79f1a48358f392841e9c9031Stephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Boschstatic void
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_rcpt_reply_overquota(struct lmtp_local_recipient *rcpt,
c23717da4af9d3275cb45cbc67faaa8daa353ec1Stephan Bosch struct smtp_server_cmd_ctx *cmd,
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch const char *error)
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch{
2bf919786518d138cc07d9cc21e14ad5e07e5e56Stephan Bosch struct smtp_address *address = rcpt->rcpt.path;
f8d9e6c977847a411af9986c9be62f74e4b06143Stephan Bosch unsigned int rcpt_idx = rcpt->rcpt.index;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch struct lda_settings *lda_set =
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch mail_storage_service_user_get_set(rcpt->service_user)[2];
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch
f8d9e6c977847a411af9986c9be62f74e4b06143Stephan Bosch i_assert(rcpt_idx == 0 || rcpt->rcpt.rcpt_cmd == NULL);
f8d9e6c977847a411af9986c9be62f74e4b06143Stephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch if (lda_set->quota_full_tempfail) {
f8d9e6c977847a411af9986c9be62f74e4b06143Stephan Bosch smtp_server_reply_index(cmd, rcpt_idx, 452, "4.2.2", "<%s> %s",
f8d9e6c977847a411af9986c9be62f74e4b06143Stephan Bosch smtp_address_encode(address), error);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch } else {
f8d9e6c977847a411af9986c9be62f74e4b06143Stephan Bosch smtp_server_reply_index(cmd, rcpt_idx, 552, "5.2.2", "<%s> %s",
f8d9e6c977847a411af9986c9be62f74e4b06143Stephan Bosch smtp_address_encode(address), error);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch }
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch}
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Boschstatic void ATTR_FORMAT(5,6)
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Boschlmtp_local_rcpt_fail_all(struct lmtp_local *local,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch unsigned int status, const char *enh_code,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch const char *fmt, ...)
420dc25a312689198499a7d1a917f54da24e506fStephan Bosch{
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct lmtp_local_recipient *const *rcpts;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch const char *msg;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch unsigned int count, i;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch va_list args;
420dc25a312689198499a7d1a917f54da24e506fStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch va_start(args, fmt);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch msg = t_strdup_vprintf(fmt, args);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch va_end(args);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch rcpts = array_get(&local->rcpt_to, &count);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch for (i = 0; i < count; i++) {
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply_index(cmd, rcpts[i]->rcpt.index,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch status, enh_code, "<%s> %s",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(rcpts[i]->rcpt.rcpt->path), msg);
420dc25a312689198499a7d1a917f54da24e506fStephan Bosch }
420dc25a312689198499a7d1a917f54da24e506fStephan Bosch}
420dc25a312689198499a7d1a917f54da24e506fStephan Bosch
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch/*
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch * RCPT command
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch */
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Boschstatic void lmtp_local_rcpt_cmd_destroy(struct smtp_server_cmd_ctx *cmd)
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch{
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch struct lmtp_local_recipient *rcpt =
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch (struct lmtp_local_recipient *)cmd->context;
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch if (rcpt == NULL)
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch return;
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch /* failed in RCPT command; clean up early */
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch lmtp_local_rcpt_deinit(rcpt);
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch return;
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch}
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch
1d2e367e199368932c02a306ddedbc7566553a15Stephan Boschstatic int
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_rcpt_check_quota(struct lmtp_local_recipient *rcpt)
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch{
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct client *client = rcpt->rcpt.client;
cdbcc8db8e0a04b2cbf6ca9f20b3ee7f7173552dStephan Bosch struct smtp_server_cmd_ctx *cmd = rcpt->rcpt.rcpt_cmd;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_address *address = rcpt->rcpt.path;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch struct mail_user *user;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch struct mail_namespace *ns;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch struct mailbox *box;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch struct mailbox_status status;
755372f8ed9aa3440cb0aa53e7f131694fb654faStephan Bosch enum mail_error mail_error;
755372f8ed9aa3440cb0aa53e7f131694fb654faStephan Bosch const char *error;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch int ret;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch if (!client->lmtp_set->lmtp_rcpt_check_quota)
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch return 0;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch /* mail user will be created second time when mail is saved,
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch so it's session_id needs to be different,
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch but second time session_id needs to be the same as rcpt session_id and
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch mail user session id for the first rcpt should not overlap with session id
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch of the second recipient, so add custom ":quota" suffix to the session_id without
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch session_id counter increment, so next time mail user will get
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch the same session id as rcpt */
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch ret = mail_storage_service_next_with_session_suffix(storage_service,
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch rcpt->service_user,
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch "quota",
755372f8ed9aa3440cb0aa53e7f131694fb654faStephan Bosch &user, &error);
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch if (ret < 0) {
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch i_error("Failed to initialize user %s: %s",
755372f8ed9aa3440cb0aa53e7f131694fb654faStephan Bosch smtp_address_encode(address), error);
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch ret = -1;
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch } else {
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch ns = mail_namespace_find_inbox(user->namespaces);
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch box = mailbox_alloc(ns->list, "INBOX", 0);
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch mailbox_set_reason(box, "over-quota check");
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch ret = mailbox_get_status(box, STATUS_CHECK_OVER_QUOTA, &status);
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch if (ret < 0) {
755372f8ed9aa3440cb0aa53e7f131694fb654faStephan Bosch error = mailbox_get_last_error(box, &mail_error);
755372f8ed9aa3440cb0aa53e7f131694fb654faStephan Bosch if (mail_error == MAIL_ERROR_NOQUOTA) {
c23717da4af9d3275cb45cbc67faaa8daa353ec1Stephan Bosch lmtp_local_rcpt_reply_overquota(rcpt, cmd, error);
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch } else {
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch i_error("mailbox_get_status(%s, STATUS_CHECK_OVER_QUOTA) "
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch "failed: %s",
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch mailbox_get_vname(box),
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch mailbox_get_last_internal_error(box, NULL));
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch }
89ec71829cca54452078c21789cd8f31925e6e99Stephan Bosch ret = -1;
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch }
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch mailbox_free(&box);
6fe14de90326d137e8a79c4fa02bbc4981f8c5faStephan Bosch mail_user_unref(&user);
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch }
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch
89ec71829cca54452078c21789cd8f31925e6e99Stephan Bosch if (ret < 0 &&
cdbcc8db8e0a04b2cbf6ca9f20b3ee7f7173552dStephan Bosch !smtp_server_command_is_replied(cmd->cmd)) {
cdbcc8db8e0a04b2cbf6ca9f20b3ee7f7173552dStephan Bosch smtp_server_reply(cmd, 451, "4.3.0",
cdbcc8db8e0a04b2cbf6ca9f20b3ee7f7173552dStephan Bosch "<%s> Temporary internal error",
cdbcc8db8e0a04b2cbf6ca9f20b3ee7f7173552dStephan Bosch smtp_address_encode(address));
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch }
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch return ret;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch}
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Boschstatic void lmtp_local_rcpt_finished(
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd,
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch struct smtp_server_transaction *trans,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_recipient *trcpt,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch unsigned int index)
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch{
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct lmtp_local_recipient *rcpt =
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch (struct lmtp_local_recipient *)cmd->context;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct client *client = rcpt->rcpt.client;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch cmd->context = NULL;
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch if (!smtp_server_command_replied_success(cmd->cmd)) {
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch /* failed in RCPT command; clean up early */
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch lmtp_local_rcpt_deinit(rcpt);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch return;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch }
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
c116e589182c258b463850327755e6dd9a731616Stephan Bosch lmtp_recipient_finish(&rcpt->rcpt, trcpt, index);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch /* resolve duplicate recipient */
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch rcpt->duplicate = (struct lmtp_local_recipient *)
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch lmtp_recipient_find_duplicate(&rcpt->rcpt, trans);
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch i_assert(rcpt->duplicate == NULL || rcpt->duplicate->duplicate == NULL);
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch /* add to local recipients */
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch array_append(&client->local->rcpt_to, &rcpt, 1);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch}
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Boschstatic bool
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_rcpt_anvil_finish(struct lmtp_local_recipient *rcpt)
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch{
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd = rcpt->rcpt.rcpt_cmd;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch int ret;
0029bf606761c2adb611571c00cad699ae37c36aStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch if ((ret = lmtp_local_rcpt_check_quota(rcpt)) < 0) {
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch cmd->context = NULL;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch lmtp_local_rcpt_deinit(rcpt);
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch return FALSE;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch }
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply(cmd, 250, "2.1.5", "OK");
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch return TRUE;
1d2e367e199368932c02a306ddedbc7566553a15Stephan Bosch}
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Boschstatic void
eb61a9ec4673adbc33d15be920cef99fd3657352Stephan Boschlmtp_local_rcpt_anvil_cb(const char *reply, void *context)
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch{
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct lmtp_local_recipient *rcpt =
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch (struct lmtp_local_recipient *)context;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd = rcpt->rcpt.rcpt_cmd;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct client *client = rcpt->rcpt.client;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_address *address = rcpt->rcpt.path;
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch const struct mail_storage_service_input *input;
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch unsigned int parallel_count = 0;
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch rcpt->anvil_query = NULL;
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch if (reply == NULL) {
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch /* lookup failed */
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch } else if (str_to_uint(reply, &parallel_count) < 0) {
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch i_error("Invalid reply from anvil: %s", reply);
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch }
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch if (parallel_count >= client->lmtp_set->lmtp_user_concurrency_limit) {
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply(cmd, 451, "4.3.0",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch "<%s> Too many concurrent deliveries for user",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(address));
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch } else if (lmtp_local_rcpt_anvil_finish(rcpt)) {
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch rcpt->anvil_connect_sent = TRUE;
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch input = mail_storage_service_user_get_input(rcpt->service_user);
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch master_service_anvil_send(master_service, t_strconcat(
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch "CONNECT\t", my_pid, "\t", master_service_get_name(master_service),
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch "/", input->username, "\n", NULL));
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch }
a3259cc32f0d62c6e495b959393b2c2f4184167bStephan Bosch}
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Boschint lmtp_local_rcpt(struct client *client,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_rcpt *data,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch const char *username, const char *detail)
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch{
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_connection *conn = cmd->conn;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch const struct smtp_address *address = data->path;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_transaction *trans;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local_recipient *rcpt;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch struct mail_storage_service_input input;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mail_storage_service_user *service_user;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch const char *session_id, *error = NULL;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch int ret = 0;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch trans = smtp_server_connection_get_transaction(conn);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch i_assert(trans != NULL); /* MAIL command is synchronous */
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch /* Use a unique session_id for each mail delivery. This is especially
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch important for stats process to not see duplicate sessions. */
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch client->state.session_id_seq++;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch if (client->state.session_id_seq == 1)
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch session_id = trans->id;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch else {
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch session_id = t_strdup_printf("%s:%u",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch trans->id, client->state.session_id_seq);
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch }
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch i_zero(&input);
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch input.module = input.service = "lmtp";
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch input.username = username;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch input.local_ip = client->local_ip;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch input.remote_ip = client->remote_ip;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch input.local_port = client->local_port;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch input.remote_port = client->remote_port;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch input.session_id = session_id;
211caf3c233d562b0c8137e5eefae3cb1ef13003Stephan Bosch input.conn_ssl_secured =
211caf3c233d562b0c8137e5eefae3cb1ef13003Stephan Bosch smtp_server_connection_is_ssl_secured(client->conn);
211caf3c233d562b0c8137e5eefae3cb1ef13003Stephan Bosch input.conn_secured = input.conn_ssl_secured ||
211caf3c233d562b0c8137e5eefae3cb1ef13003Stephan Bosch smtp_server_connection_is_trusted(client->conn);
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch ret = mail_storage_service_lookup(storage_service, &input,
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch &service_user, &error);
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch if (ret < 0) {
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch i_error("Failed to lookup user %s: %s", username, error);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply(cmd, 451, "4.3.0",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch "<%s> Temporary internal error",
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch smtp_address_encode(address));
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch return -1;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch }
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch if (ret == 0) {
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply(cmd, 550, "5.1.1",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch "<%s> User doesn't exist: %s",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(address), username);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch return -1;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch }
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch if (client->local == NULL)
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch client->local = lmtp_local_init(client);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch rcpt = i_new(struct lmtp_local_recipient, 1);
11c80f46431050af464b044126887e81cb91e929Stephan Bosch lmtp_recipient_init(&rcpt->rcpt, client,
11c80f46431050af464b044126887e81cb91e929Stephan Bosch LMTP_RECIPIENT_TYPE_LOCAL, cmd, data);
c116e589182c258b463850327755e6dd9a731616Stephan Bosch
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch rcpt->detail = i_strdup(detail);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch rcpt->service_user = service_user;
252a2911d1f9dd0ce7dc6753981e0ad376c2fe9eStephan Bosch rcpt->session_id = i_strdup(session_id);
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch cmd->context = (void*)rcpt;
540ac35c2e2e0a88619c2224a9cccef51fecc37cStephan Bosch cmd->hook_destroy = lmtp_local_rcpt_cmd_destroy;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch data->hook_finished = lmtp_local_rcpt_finished;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch if (client->lmtp_set->lmtp_user_concurrency_limit == 0) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch (void)lmtp_local_rcpt_anvil_finish(rcpt);
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch } else {
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch /* NOTE: username may change as the result of the userdb
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch lookup. Look up the new one via service_user. */
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch const struct mail_storage_service_input *input =
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch mail_storage_service_user_get_input(rcpt->service_user);
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch const char *query = t_strconcat("LOOKUP\t",
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch master_service_get_name(master_service),
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch "/", str_tabescape(input->username), NULL);
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch rcpt->anvil_query = anvil_client_query(anvil, query,
eb61a9ec4673adbc33d15be920cef99fd3657352Stephan Bosch lmtp_local_rcpt_anvil_cb, rcpt);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch return 0;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch }
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch return 1;
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch}
bc1306f129e92eae1738a544a89bd7b2e4f6f735Stephan Bosch
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch/*
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch * DATA command
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch */
1c1396ed2f41328c88c1cfd73cb0168389507123Stephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschvoid lmtp_local_add_headers(struct lmtp_local *local,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_transaction *trans,
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch string_t *headers)
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch{
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local_recipient *const *rcpts;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch const struct lmtp_settings *lmtp_set;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch const struct smtp_address *rcpt_to = NULL;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch unsigned int count;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch void **sets;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch str_printfa(headers, "Return-Path: <%s>\r\n",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(trans->mail_from));
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch rcpts = array_get(&local->rcpt_to, &count);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch if (count == 1) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch sets = mail_storage_service_user_get_set(rcpts[0]->service_user);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch lmtp_set = sets[3];
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch switch (lmtp_set->parsed_lmtp_hdr_delivery_address) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch case LMTP_HDR_DELIVERY_ADDRESS_NONE:
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch break;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch case LMTP_HDR_DELIVERY_ADDRESS_FINAL:
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch rcpt_to = rcpts[0]->rcpt.rcpt->path;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch break;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch case LMTP_HDR_DELIVERY_ADDRESS_ORIGINAL:
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch rcpt_to = rcpts[0]->rcpt.rcpt->params.orcpt.addr;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch break;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch }
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch }
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch if (rcpt_to != NULL) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch str_printfa(headers, "Delivered-To: %s\r\n",
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch smtp_address_encode(rcpt_to));
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch }
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch}
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Boschstatic int
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_deliver(struct lmtp_local *local,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_transaction *trans,
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local_recipient *rcpt,
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mail *src_mail,
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mail_deliver_session *session)
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch{
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct client *client = local->client;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_address *rcpt_to = rcpt->rcpt.rcpt->path;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch unsigned int rcpt_idx = rcpt->rcpt.index;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch const struct smtp_server_recipient *trcpt =
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch *array_idx(&trans->rcpt_to, rcpt_idx);
28585a42776a3e2bc530e604e21446832975b816Stephan Bosch struct mail_storage_service_user *service_user = rcpt->service_user;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch struct mail_deliver_context dctx;
4bc2df90527f33dc51a9f367b64f18751c88ee25Stephan Bosch struct mail_user *rcpt_user;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch struct mail_storage *storage;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch const struct mail_storage_service_input *input;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch const struct mail_storage_settings *mail_set;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch struct smtp_submit_settings *smtp_set;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_proxy_data proxy_data;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch struct lda_settings *lda_set;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch struct mail_namespace *ns;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch struct setting_parser_context *set_parser;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch const struct var_expand_table *var_table;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch struct timeval delivery_time_started;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch void **sets;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch const char *line, *error, *username;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch string_t *str;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch enum mail_error mail_error;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch int ret;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
28585a42776a3e2bc530e604e21446832975b816Stephan Bosch input = mail_storage_service_user_get_input(service_user);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch username = t_strdup(input->username);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
28585a42776a3e2bc530e604e21446832975b816Stephan Bosch mail_set = mail_storage_service_user_get_mail_set(service_user);
28585a42776a3e2bc530e604e21446832975b816Stephan Bosch set_parser = mail_storage_service_user_get_settings_parser(service_user);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_connection_get_proxy_data
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch (client->conn, &proxy_data);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch if (proxy_data.timeout_secs > 0 &&
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch (mail_set->mail_max_lock_timeout == 0 ||
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch mail_set->mail_max_lock_timeout > proxy_data.timeout_secs)) {
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch /* set lock timeout waits to be less than when proxy has
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch advertised that it's going to timeout the connection.
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch this avoids duplicate deliveries in case the delivery
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch succeeds after the proxy has already disconnected from us. */
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch line = t_strdup_printf("mail_max_lock_timeout=%us",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch proxy_data.timeout_secs <= 1 ? 1 :
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch proxy_data.timeout_secs-1);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch if (settings_parse_line(set_parser, line) < 0)
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch i_unreached();
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch /* get the timestamp before user is created, since it starts the I/O */
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch io_loop_time_refresh();
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch delivery_time_started = ioloop_timeval;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch i_set_failure_prefix("lmtp(%s, %s): ", my_pid, username);
28585a42776a3e2bc530e604e21446832975b816Stephan Bosch if (mail_storage_service_next(storage_service, service_user,
4bc2df90527f33dc51a9f367b64f18751c88ee25Stephan Bosch &rcpt_user, &error) < 0) {
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch i_error("Failed to initialize user: %s", error);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply_index(cmd, rcpt_idx, 451, "4.3.0",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch "<%s> Temporary internal error",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(rcpt_to));
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch return -1;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local->rcpt_user = rcpt_user;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
28585a42776a3e2bc530e604e21446832975b816Stephan Bosch sets = mail_storage_service_user_get_set(service_user);
4bc2df90527f33dc51a9f367b64f18751c88ee25Stephan Bosch var_table = mail_user_var_expand_table(rcpt_user);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch smtp_set = sets[1];
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch lda_set = sets[2];
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch ret = settings_var_expand(
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch &smtp_submit_setting_parser_info,
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch smtp_set, client->pool, var_table,
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch &error);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch if (ret > 0) {
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch ret = settings_var_expand(
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch &lda_setting_parser_info,
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch lda_set, client->pool, var_table,
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch &error);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch if (ret <= 0) {
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch i_error("Failed to expand settings: %s", error);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply_index(cmd, rcpt_idx, 451, "4.3.0",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch "<%s> Temporary internal error",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(rcpt_to));
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch return -1;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch str = t_str_new(256);
4bc2df90527f33dc51a9f367b64f18751c88ee25Stephan Bosch if (var_expand_with_funcs(str, rcpt_user->set->mail_log_prefix,
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch var_table, mail_user_var_expand_func_table,
4bc2df90527f33dc51a9f367b64f18751c88ee25Stephan Bosch rcpt_user, &error) <= 0) {
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch i_error("Failed to expand mail_log_prefix=%s: %s",
4bc2df90527f33dc51a9f367b64f18751c88ee25Stephan Bosch rcpt_user->set->mail_log_prefix, error);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply_index(cmd, rcpt_idx, 451, "4.3.0",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch "<%s> Temporary internal error",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(rcpt_to));
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch return -1;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch i_set_failure_prefix("%s", str_c(str));
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch i_zero(&dctx);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.session = session;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.pool = session->pool;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.set = lda_set;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.smtp_set = smtp_set;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.session_id = rcpt->session_id;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.src_mail = src_mail;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch /* MAIL FROM */
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch dctx.mail_from = trans->mail_from;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_params_mail_copy(dctx.pool,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch &dctx.mail_params, &trans->params);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch /* RCPT TO */
4bc2df90527f33dc51a9f367b64f18751c88ee25Stephan Bosch dctx.rcpt_user = rcpt_user;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_params_rcpt_copy(dctx.pool,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch &dctx.rcpt_params, &trcpt->params);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch if (dctx.rcpt_params.orcpt.addr == NULL &&
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch *dctx.set->lda_original_recipient_header != '\0') {
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch dctx.rcpt_params.orcpt.addr =
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch mail_deliver_get_address(src_mail,
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.set->lda_original_recipient_header);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch if (dctx.rcpt_params.orcpt.addr == NULL)
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch dctx.rcpt_params.orcpt.addr = rcpt_to;
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch dctx.rcpt_to = rcpt_to;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch if (*rcpt->detail == '\0' ||
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch !client->lmtp_set->lmtp_save_to_detail_mailbox)
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.rcpt_default_mailbox = "INBOX";
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch else {
4bc2df90527f33dc51a9f367b64f18751c88ee25Stephan Bosch ns = mail_namespace_find_inbox(rcpt_user->namespaces);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.rcpt_default_mailbox =
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch t_strconcat(ns->prefix, rcpt->detail, NULL);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch dctx.save_dest_mail = array_count(&trans->rcpt_to) > 1 &&
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local->first_saved_mail == NULL;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.session_time_msecs =
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch timeval_diff_msecs(&client->state.data_end_timeval,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch &trans->timestamp);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch dctx.delivery_time_started = delivery_time_started;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch if (mail_deliver(&dctx, &storage) == 0) {
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch if (dctx.dest_mail != NULL) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch i_assert(local->first_saved_mail == NULL);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local->first_saved_mail = dctx.dest_mail;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply_index(cmd, rcpt_idx,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch 250, "2.0.0", "<%s> %s Saved",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(rcpt_to), rcpt->session_id);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch ret = 0;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch } else if (dctx.tempfail_error != NULL) {
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply_index(cmd, rcpt_idx,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch 451, "4.2.0", "<%s> %s",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(rcpt_to),
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch dctx.tempfail_error);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch ret = -1;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch } else if (storage != NULL) {
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch error = mail_storage_get_last_error(storage, &mail_error);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch if (mail_error == MAIL_ERROR_NOQUOTA) {
c23717da4af9d3275cb45cbc67faaa8daa353ec1Stephan Bosch lmtp_local_rcpt_reply_overquota(rcpt, cmd, error);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch } else {
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply_index(cmd, rcpt_idx,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch 451, "4.2.0", "<%s> %s",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(rcpt_to), error);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch ret = -1;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch } else {
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch /* This shouldn't happen */
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch i_error("BUG: Saving failed to unknown storage");
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_server_reply_index(cmd, rcpt_idx, 451, "4.3.0",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch "<%s> Temporary internal error",
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch smtp_address_encode(rcpt_to));
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch ret = -1;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch }
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch lmtp_local_rcpt_anvil_disconnect(rcpt);
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch return ret;
4c10d203d1581b9e850a0e4552567fe7fec9598bStephan Bosch}
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch
dafe3306912b5c0904e53fac3928863474d1c1e8Stephan Boschstatic uid_t
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_deliver_to_rcpts(struct lmtp_local *local,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_transaction *trans,
dafe3306912b5c0904e53fac3928863474d1c1e8Stephan Bosch struct mail_deliver_session *session)
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch{
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch uid_t first_uid = (uid_t)-1;
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch struct mail *src_mail;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local_recipient *const *rcpts;
ce7a45d15786c7434546bd9da60fae08fc157f13Stephan Bosch unsigned int count, i;
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch int ret;
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch src_mail = local->raw_mail;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch rcpts = array_get(&local->rcpt_to, &count);
ce7a45d15786c7434546bd9da60fae08fc157f13Stephan Bosch for (i = 0; i < count; i++) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local_recipient *rcpt = rcpts[i];
ce7a45d15786c7434546bd9da60fae08fc157f13Stephan Bosch
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch if (rcpt->duplicate != NULL) {
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch /* don't deliver more than once to the same recipient */
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch smtp_server_reply_submit_duplicate(cmd,
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch rcpt->rcpt.index, rcpt->duplicate->rcpt.index);
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch continue;
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch }
80f5e1ea615677c1c37be6e7abb888c9cc22de3bStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch ret = lmtp_local_deliver(local, cmd,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch trans, rcpt, src_mail, session);
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch i_set_failure_prefix("lmtp(%s): ", my_pid);
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch /* succeeded and mail_user is not saved in first_saved_mail */
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch if ((ret == 0 &&
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch (local->first_saved_mail == NULL ||
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local->first_saved_mail == src_mail)) ||
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch /* failed. try the next one. */
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch (ret != 0 && local->rcpt_user != NULL)) {
ce7a45d15786c7434546bd9da60fae08fc157f13Stephan Bosch if (i == (count - 1))
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch mail_user_autoexpunge(local->rcpt_user);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch mail_user_unref(&local->rcpt_user);
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch } else if (ret == 0) {
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch /* use the first saved message to save it elsewhere too.
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch this might allow hard linking the files.
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch mail_user is saved in first_saved_mail,
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch will be unreferenced later on */
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local->rcpt_user = NULL;
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch src_mail = local->first_saved_mail;
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch first_uid = geteuid();
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch i_assert(first_uid != 0);
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch }
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch }
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch return first_uid;
fb2e20a30de93e83bbfe407f8231181f69ae684fStephan Bosch}
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch
d14a8963103ecea8e3cf5191122d189552f7d50aStephan Boschstatic int
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Boschlmtp_local_open_raw_mail(struct lmtp_local *local,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_transaction *trans,
d14a8963103ecea8e3cf5191122d189552f7d50aStephan Bosch struct istream *input)
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch{
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch static const char *wanted_headers[] = {
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch "From", "To", "Message-ID", "Subject", "Return-Path",
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch NULL
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch };
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct client *client = local->client;
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch struct mailbox *box;
cfc330f2ca4d1a8f9091c01305bb7f665f256798Stephan Bosch struct mailbox_transaction_context *mtrans;
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch struct mailbox_header_lookup_ctx *headers_ctx;
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch enum mail_error error;
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch if (raw_mailbox_alloc_stream(client->raw_mail_user, input,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch (time_t)-1, smtp_address_encode(trans->mail_from),
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch &box) < 0) {
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch i_error("Can't open delivery mail as raw: %s",
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch mailbox_get_last_internal_error(box, &error));
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch mailbox_free(&box);
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch lmtp_local_rcpt_fail_all(local, cmd,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch 451, "4.3.0", "Temporary internal error");
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch return -1;
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch }
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch
cfc330f2ca4d1a8f9091c01305bb7f665f256798Stephan Bosch mtrans = mailbox_transaction_begin(box, 0, __func__);
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch headers_ctx = mailbox_header_lookup_init(box, wanted_headers);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch local->raw_mail = mail_alloc(mtrans, 0, headers_ctx);
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch mailbox_header_lookup_unref(&headers_ctx);
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch mail_set_seq(local->raw_mail, 1);
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch return 0;
e3d554ca3408b7ea692f6f0b9ef5e6579e345627Stephan Bosch}
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Boschvoid lmtp_local_data(struct client *client,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_cmd_ctx *cmd,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct smtp_server_transaction *trans,
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch struct istream *input)
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch{
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct lmtp_local *local = client->local;
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch struct mail_deliver_session *session;
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch uid_t old_uid, first_uid;
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch if (lmtp_local_open_raw_mail(local, cmd, trans, input) < 0)
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch return;
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch session = mail_deliver_session_init();
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch old_uid = geteuid();
b73539ef2de3db3abc0ad5f729406e695e4cb76bStephan Bosch first_uid = lmtp_local_deliver_to_rcpts(local, cmd, trans, session);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch mail_deliver_session_deinit(&session);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch if (local->first_saved_mail != NULL) {
2b7d6fbaadd62e66c858bae0358232c02369b43bStephan Bosch struct mail *mail = local->first_saved_mail;
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch struct mailbox_transaction_context *trans = mail->transaction;
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch struct mailbox *box = trans->box;
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch struct mail_user *user = box->storage->user;
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch /* just in case these functions are going to write anything,
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch change uid back to user's own one */
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch if (first_uid != old_uid) {
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch if (seteuid(0) < 0)
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch i_fatal("seteuid(0) failed: %m");
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch if (seteuid(first_uid) < 0)
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch i_fatal("seteuid() failed: %m");
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch }
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch mail_free(&mail);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch mailbox_transaction_rollback(&trans);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch mailbox_free(&box);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch mail_user_autoexpunge(user);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch mail_user_unref(&user);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch }
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch if (old_uid == 0) {
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch /* switch back to running as root, since that's what we're
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch practically doing anyway. it's also important in case we
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch lose e.g. config connection and need to reconnect to it. */
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch if (seteuid(0) < 0)
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch i_fatal("seteuid(0) failed: %m");
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch /* enable core dumping again. we need to chdir also to
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch root-owned directory to get core dumps. */
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch restrict_access_allow_coredumps(TRUE);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch if (chdir(base_dir) < 0)
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch i_error("chdir(%s) failed: %m", base_dir);
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch }
cbd1d1a197f57d894c22863058b0ea3f2d2f68ffStephan Bosch}