11af4fa4bSClemens Zeidler/*
281805393SAxel Dörfler * Copyright 2007-2016, Haiku, Inc. All rights reserved.
31af4fa4bSClemens Zeidler * Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved.
41af4fa4bSClemens Zeidler * Copyright 2011, Clemens Zeidler <haiku@clemens-zeidler.de>
51af4fa4bSClemens Zeidler * Distributed under the terms of the MIT License.
61af4fa4bSClemens Zeidler */
71af4fa4bSClemens Zeidler
81af4fa4bSClemens Zeidler
9daf972c9SAxel Dörfler#include "MailDaemonApplication.h"
101af4fa4bSClemens Zeidler
111af4fa4bSClemens Zeidler#include <stdio.h>
121af4fa4bSClemens Zeidler#include <stdlib.h>
131af4fa4bSClemens Zeidler#include <vector>
141af4fa4bSClemens Zeidler
151af4fa4bSClemens Zeidler#include <Beep.h>
16c26c18e4SClemens Zeidler#include <Catalog.h>
171af4fa4bSClemens Zeidler#include <Deskbar.h>
181af4fa4bSClemens Zeidler#include <Directory.h>
191af4fa4bSClemens Zeidler#include <Entry.h>
201af4fa4bSClemens Zeidler#include <FindDirectory.h>
211af4fa4bSClemens Zeidler#include <fs_index.h>
22244a5450SAdrien Destugues#include <IconUtils.h>
231af4fa4bSClemens Zeidler#include <NodeMonitor.h>
24701d9285SAdrien Destugues#include <Notification.h>
251af4fa4bSClemens Zeidler#include <Path.h>
261af4fa4bSClemens Zeidler#include <Roster.h>
271af4fa4bSClemens Zeidler#include <StringList.h>
287457ccb4SAugustin Cavalier#include <StringFormat.h>
291af4fa4bSClemens Zeidler#include <VolumeRoster.h>
301af4fa4bSClemens Zeidler
311af4fa4bSClemens Zeidler#include <E-mail.h>
321af4fa4bSClemens Zeidler#include <MailDaemon.h>
331af4fa4bSClemens Zeidler#include <MailMessage.h>
341af4fa4bSClemens Zeidler#include <MailSettings.h>
35c26c18e4SClemens Zeidler
36146357b5SAxel Dörfler#include <MailPrivate.h>
37146357b5SAxel Dörfler
38c26c18e4SClemens Zeidler
39546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
40546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "MailDaemon"
411af4fa4bSClemens Zeidler
421af4fa4bSClemens Zeidler
438705e1f6SAxel Dörflerstatic const uint32 kMsgStartAutoCheck = 'stAC';
444cab719fSAxel Dörflerstatic const uint32 kMsgAutoCheck = 'moto';
454cab719fSAxel Dörfler
468705e1f6SAxel Dörflerstatic const bigtime_t kStartAutoCheckDelay = 30000000;
478705e1f6SAxel Dörfler	// Wait 30 seconds before the first auto check - this usually lets the
488705e1f6SAxel Dörfler	// boot process settle down, and give the network a chance to come up.
498705e1f6SAxel Dörfler
504cab719fSAxel Dörfler
51d396412dSAxel Dörflerstruct send_mails_info {
52d396412dSAxel Dörfler	send_mails_info()
53d396412dSAxel Dörfler	{
54146357b5SAxel Dörfler		bytes = 0;
55146357b5SAxel Dörfler	}
56146357b5SAxel Dörfler
57146357b5SAxel Dörfler	BMessage	files;
58146357b5SAxel Dörfler	off_t		bytes;
59146357b5SAxel Dörfler};
60146357b5SAxel Dörfler
61146357b5SAxel Dörfler
62146357b5SAxel Dörflerclass InboundMessenger : public BMessenger {
63146357b5SAxel Dörflerpublic:
64146357b5SAxel Dörfler	InboundMessenger(BInboundMailProtocol* protocol)
65146357b5SAxel Dörfler		:
66146357b5SAxel Dörfler		BMessenger(protocol)
67146357b5SAxel Dörfler	{
68146357b5SAxel Dörfler	}
69146357b5SAxel Dörfler
70146357b5SAxel Dörfler	status_t MarkAsRead(const entry_ref& ref, read_flags flag)
71146357b5SAxel Dörfler	{
72146357b5SAxel Dörfler		BMessage message(kMsgMarkMessageAsRead);
73146357b5SAxel Dörfler		message.AddRef("ref", &ref);
74146357b5SAxel Dörfler		message.AddInt32("read", flag);
75146357b5SAxel Dörfler
76146357b5SAxel Dörfler		return SendMessage(&message);
77146357b5SAxel Dörfler	}
78146357b5SAxel Dörfler
79146357b5SAxel Dörfler	status_t SynchronizeMessages()
80146357b5SAxel Dörfler	{
81146357b5SAxel Dörfler		BMessage message(kMsgSyncMessages);
82146357b5SAxel Dörfler		return SendMessage(&message);
83d396412dSAxel Dörfler	}
84146357b5SAxel Dörfler};
85146357b5SAxel Dörfler
86146357b5SAxel Dörfler
87d396412dSAxel Dörfler// #pragma mark -
88d396412dSAxel Dörfler
89d396412dSAxel Dörfler
90d396412dSAxel Dörflerstatic void
911af4fa4bSClemens ZeidlermakeIndices()
921af4fa4bSClemens Zeidler{
931af4fa4bSClemens Zeidler	const char* stringIndices[] = {
941af4fa4bSClemens Zeidler		B_MAIL_ATTR_CC, B_MAIL_ATTR_FROM, B_MAIL_ATTR_NAME,
951af4fa4bSClemens Zeidler		B_MAIL_ATTR_PRIORITY, B_MAIL_ATTR_REPLY, B_MAIL_ATTR_STATUS,
961af4fa4bSClemens Zeidler		B_MAIL_ATTR_SUBJECT, B_MAIL_ATTR_TO, B_MAIL_ATTR_THREAD,
97a1f765fbSClemens Zeidler		B_MAIL_ATTR_ACCOUNT, NULL
981af4fa4bSClemens Zeidler	};
991af4fa4bSClemens Zeidler
1001af4fa4bSClemens Zeidler	// add mail indices for all devices capable of querying
1011af4fa4bSClemens Zeidler
1021af4fa4bSClemens Zeidler	int32 cookie = 0;
1031af4fa4bSClemens Zeidler	dev_t device;
1041af4fa4bSClemens Zeidler	while ((device = next_dev(&cookie)) >= B_OK) {
1051af4fa4bSClemens Zeidler		fs_info info;
1061af4fa4bSClemens Zeidler		if (fs_stat_dev(device, &info) < 0
1071af4fa4bSClemens Zeidler			|| (info.flags & B_FS_HAS_QUERY) == 0)
1081af4fa4bSClemens Zeidler			continue;
1091af4fa4bSClemens Zeidler
1101af4fa4bSClemens Zeidler		for (int32 i = 0; stringIndices[i]; i++)
1111af4fa4bSClemens Zeidler			fs_create_index(device, stringIndices[i], B_STRING_TYPE, 0);
1121af4fa4bSClemens Zeidler
1131af4fa4bSClemens Zeidler		fs_create_index(device, "MAIL:draft", B_INT32_TYPE, 0);
1141af4fa4bSClemens Zeidler		fs_create_index(device, B_MAIL_ATTR_WHEN, B_INT32_TYPE, 0);
1151af4fa4bSClemens Zeidler		fs_create_index(device, B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0);
116a1f765fbSClemens Zeidler		fs_create_index(device, B_MAIL_ATTR_ACCOUNT_ID, B_INT32_TYPE, 0);
1179967dfd9SClemens Zeidler		fs_create_index(device, B_MAIL_ATTR_READ, B_INT32_TYPE, 0);
1181af4fa4bSClemens Zeidler	}
1191af4fa4bSClemens Zeidler}
1201af4fa4bSClemens Zeidler
1211af4fa4bSClemens Zeidler
122d396412dSAxel Dörflerstatic void
1231af4fa4bSClemens ZeidleraddAttribute(BMessage& msg, const char* name, const char* publicName,
1241af4fa4bSClemens Zeidler	int32 type = B_STRING_TYPE, bool viewable = true, bool editable = false,
1251af4fa4bSClemens Zeidler	int32 width = 200)
1261af4fa4bSClemens Zeidler{
1271af4fa4bSClemens Zeidler	msg.AddString("attr:name", name);
1281af4fa4bSClemens Zeidler	msg.AddString("attr:public_name", publicName);
1291af4fa4bSClemens Zeidler	msg.AddInt32("attr:type", type);
1301af4fa4bSClemens Zeidler	msg.AddBool("attr:viewable", viewable);
1311af4fa4bSClemens Zeidler	msg.AddBool("attr:editable", editable);
1321af4fa4bSClemens Zeidler	msg.AddInt32("attr:width", width);
1331af4fa4bSClemens Zeidler	msg.AddInt32("attr:alignment", B_ALIGN_LEFT);
1341af4fa4bSClemens Zeidler}
1351af4fa4bSClemens Zeidler
1361af4fa4bSClemens Zeidler
137146357b5SAxel Dörfler// #pragma mark -
138146357b5SAxel Dörfler
139146357b5SAxel Dörfler
140146357b5SAxel Dörfleraccount_protocols::account_protocols()
141146357b5SAxel Dörfler	:
142146357b5SAxel Dörfler	inboundImage(-1),
143146357b5SAxel Dörfler	inboundProtocol(NULL),
144146357b5SAxel Dörfler	outboundImage(-1),
145146357b5SAxel Dörfler	outboundProtocol(NULL)
146146357b5SAxel Dörfler{
147146357b5SAxel Dörfler}
148146357b5SAxel Dörfler
149146357b5SAxel Dörfler
150146357b5SAxel Dörfler// #pragma mark -
1511af4fa4bSClemens Zeidler
1521af4fa4bSClemens Zeidler
153daf972c9SAxel DörflerMailDaemonApplication::MailDaemonApplication()
1541af4fa4bSClemens Zeidler	:
155893e3de8SAxel Dörfler	BServer(B_MAIL_DAEMON_SIGNATURE, true, NULL),
1561af4fa4bSClemens Zeidler	fAutoCheckRunner(NULL)
1571af4fa4bSClemens Zeidler{
1581af4fa4bSClemens Zeidler	fErrorLogWindow = new ErrorLogWindow(BRect(200, 200, 500, 250),
15983c3aba2SClemens Zeidler		B_TRANSLATE("Mail daemon status log"), B_TITLED_WINDOW);
1601af4fa4bSClemens Zeidler	// install MimeTypes, attributes, indices, and the
1611af4fa4bSClemens Zeidler	// system beep add startup
1621af4fa4bSClemens Zeidler	MakeMimeTypes();
1631af4fa4bSClemens Zeidler	makeIndices();
1641af4fa4bSClemens Zeidler	add_system_beep_event("New E-mail");
1651af4fa4bSClemens Zeidler}
1661af4fa4bSClemens Zeidler
1671af4fa4bSClemens Zeidler
168daf972c9SAxel DörflerMailDaemonApplication::~MailDaemonApplication()
1691af4fa4bSClemens Zeidler{
1701af4fa4bSClemens Zeidler	delete fAutoCheckRunner;
1711af4fa4bSClemens Zeidler
1721af4fa4bSClemens Zeidler	for (int32 i = 0; i < fQueries.CountItems(); i++)
1731af4fa4bSClemens Zeidler		delete fQueries.ItemAt(i);
1741af4fa4bSClemens Zeidler
175146357b5SAxel Dörfler	while (!fAccounts.empty()) {
176146357b5SAxel Dörfler		_RemoveAccount(fAccounts.begin()->second);
177146357b5SAxel Dörfler		fAccounts.erase(fAccounts.begin());
178146357b5SAxel Dörfler	}
179146357b5SAxel Dörfler
1801af4fa4bSClemens Zeidler	delete fLEDAnimation;
181701d9285SAdrien Destugues	delete fNotification;
1821af4fa4bSClemens Zeidler}
1831af4fa4bSClemens Zeidler
1841af4fa4bSClemens Zeidler
1851af4fa4bSClemens Zeidlervoid
186daf972c9SAxel DörflerMailDaemonApplication::ReadyToRun()
1871af4fa4bSClemens Zeidler{
1881af4fa4bSClemens Zeidler	InstallDeskbarIcon();
1891af4fa4bSClemens Zeidler
1901af4fa4bSClemens Zeidler	_InitAccounts();
1911af4fa4bSClemens Zeidler
1928705e1f6SAxel Dörfler	// Start auto mail check with a delay
1938705e1f6SAxel Dörfler	BMessage startAutoCheck(kMsgStartAutoCheck);
1948705e1f6SAxel Dörfler	BMessageRunner::StartSending(this, &startAutoCheck,
1958705e1f6SAxel Dörfler		kStartAutoCheckDelay, 1);
1961af4fa4bSClemens Zeidler
1978705e1f6SAxel Dörfler	_InitNewMessagesCount();
198c26c18e4SClemens Zeidler
1991af4fa4bSClemens Zeidler	fCentralBeep = false;
200701d9285SAdrien Destugues
201701d9285SAdrien Destugues	fNotification = new BNotification(B_INFORMATION_NOTIFICATION);
2024ec6c3a0SAdrien Destugues	fNotification->SetGroup(B_TRANSLATE("Mail status"));
203244a5450SAdrien Destugues	fNotification->SetMessageID("daemon_status");
2048705e1f6SAxel Dörfler	_UpdateNewMessagesNotification();
205244a5450SAdrien Destugues
206244a5450SAdrien Destugues	app_info info;
207244a5450SAdrien Destugues	be_roster->GetAppInfo(B_MAIL_DAEMON_SIGNATURE, &info);
208244a5450SAdrien Destugues	BBitmap icon(BRect(0, 0, 32, 32), B_RGBA32);
209244a5450SAdrien Destugues	BNode node(&info.ref);
210244a5450SAdrien Destugues	BIconUtils::GetVectorIcon(&node, "BEOS:ICON", &icon);
211244a5450SAdrien Destugues	fNotification->SetIcon(&icon);
2121af4fa4bSClemens Zeidler
2138705e1f6SAxel Dörfler	fLEDAnimation = new LEDAnimation();
2141af4fa4bSClemens Zeidler	SetPulseRate(1000000);
2151af4fa4bSClemens Zeidler}
2161af4fa4bSClemens Zeidler
2171af4fa4bSClemens Zeidler
2181af4fa4bSClemens Zeidlervoid
219daf972c9SAxel DörflerMailDaemonApplication::RefsReceived(BMessage* message)
2201af4fa4bSClemens Zeidler{
2211af4fa4bSClemens Zeidler	entry_ref ref;
2221af4fa4bSClemens Zeidler	for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
2231af4fa4bSClemens Zeidler		BNode node(&ref);
22420537ad0SAxel Dörfler		if (node.InitCheck() != B_OK)
2251af4fa4bSClemens Zeidler			continue;
2261af4fa4bSClemens Zeidler
2271af4fa4bSClemens Zeidler		int32 account;
228a64bd564SClemens Zeidler		if (node.ReadAttr(B_MAIL_ATTR_ACCOUNT_ID, B_INT32_TYPE, 0, &account,
22920537ad0SAxel Dörfler				sizeof(account)) < 0)
2301af4fa4bSClemens Zeidler			continue;
2311af4fa4bSClemens Zeidler
232146357b5SAxel Dörfler		BInboundMailProtocol* protocol = _InboundProtocol(account);
233146357b5SAxel Dörfler		if (protocol == NULL)
2341af4fa4bSClemens Zeidler			continue;
2350e657c0bSClemens Zeidler
236b8d2bbd6SClemens Zeidler		BMessenger target;
237146357b5SAxel Dörfler		BMessenger* replyTo = &target;
238b8d2bbd6SClemens Zeidler		if (message->FindMessenger("target", &target) != B_OK)
239146357b5SAxel Dörfler			replyTo = NULL;
240146357b5SAxel Dörfler
24181805393SAxel Dörfler		protocol->FetchBody(ref, replyTo);
2421af4fa4bSClemens Zeidler	}
2431af4fa4bSClemens Zeidler}
2441af4fa4bSClemens Zeidler
2451af4fa4bSClemens Zeidler
2461af4fa4bSClemens Zeidlervoid
247daf972c9SAxel DörflerMailDaemonApplication::MessageReceived(BMessage* msg)
2481af4fa4bSClemens Zeidler{
2491af4fa4bSClemens Zeidler	switch (msg->what) {
2508705e1f6SAxel Dörfler		case kMsgStartAutoCheck:
2518705e1f6SAxel Dörfler			_UpdateAutoCheckRunner();
2528705e1f6SAxel Dörfler			break;
2538705e1f6SAxel Dörfler
2544cab719fSAxel Dörfler		case kMsgAutoCheck:
2554cab719fSAxel Dörfler			// TODO: check whether internet is up and running!
2561af4fa4bSClemens Zeidler			// supposed to fall through
2571af4fa4bSClemens Zeidler		case kMsgCheckAndSend:	// check & send messages
2581af4fa4bSClemens Zeidler			msg->what = kMsgSendMessages;
2591af4fa4bSClemens Zeidler			PostMessage(msg);
2601af4fa4bSClemens Zeidler			// supposed to fall trough
2611af4fa4bSClemens Zeidler		case kMsgCheckMessage:	// check messages
2621af4fa4bSClemens Zeidler			GetNewMessages(msg);
2631af4fa4bSClemens Zeidler			break;
2641af4fa4bSClemens Zeidler
2651af4fa4bSClemens Zeidler		case kMsgSendMessages:	// send messages
2661af4fa4bSClemens Zeidler			SendPendingMessages(msg);
2671af4fa4bSClemens Zeidler			break;
2681af4fa4bSClemens Zeidler
2691af4fa4bSClemens Zeidler		case kMsgSettingsUpdated:
2701af4fa4bSClemens Zeidler			fSettingsFile.Reload();
2718705e1f6SAxel Dörfler			_UpdateAutoCheckRunner();
2721af4fa4bSClemens Zeidler			break;
2731af4fa4bSClemens Zeidler
2741af4fa4bSClemens Zeidler		case kMsgAccountsChanged:
2751af4fa4bSClemens Zeidler			_ReloadAccounts(msg);
2761af4fa4bSClemens Zeidler			break;
2771af4fa4bSClemens Zeidler
2781af4fa4bSClemens Zeidler		case kMsgMarkMessageAsRead:
2791af4fa4bSClemens Zeidler		{
2801af4fa4bSClemens Zeidler			int32 account = msg->FindInt32("account");
2811af4fa4bSClemens Zeidler			entry_ref ref;
2821af4fa4bSClemens Zeidler			if (msg->FindRef("ref", &ref) != B_OK)
2831af4fa4bSClemens Zeidler				break;
2849967dfd9SClemens Zeidler			read_flags read = (read_flags)msg->FindInt32("read");
285146357b5SAxel Dörfler
286146357b5SAxel Dörfler			BInboundMailProtocol* protocol = _InboundProtocol(account);
287146357b5SAxel Dörfler			if (protocol != NULL)
288146357b5SAxel Dörfler				InboundMessenger(protocol).MarkAsRead(ref, read);
2891af4fa4bSClemens Zeidler			break;
2901af4fa4bSClemens Zeidler		}
2911af4fa4bSClemens Zeidler
292df0ad9c1SClemens Zeidler		case kMsgFetchBody:
293df0ad9c1SClemens Zeidler			RefsReceived(msg);
294df0ad9c1SClemens Zeidler			break;
295df0ad9c1SClemens Zeidler
2961af4fa4bSClemens Zeidler		case 'stwg':	// Status window gone
2971af4fa4bSClemens Zeidler		{
2981af4fa4bSClemens Zeidler			BMessage reply('mnuc');
2991af4fa4bSClemens Zeidler			reply.AddInt32("num_new_messages", fNewMessages);
3001af4fa4bSClemens Zeidler
3011af4fa4bSClemens Zeidler			while ((msg = fFetchDoneRespondents.RemoveItemAt(0))) {
3021af4fa4bSClemens Zeidler				msg->SendReply(&reply);
3031af4fa4bSClemens Zeidler				delete msg;
3041af4fa4bSClemens Zeidler			}
3051af4fa4bSClemens Zeidler
3061af4fa4bSClemens Zeidler			if (fAlertString != B_EMPTY_STRING) {
3071af4fa4bSClemens Zeidler				fAlertString.Truncate(fAlertString.Length() - 1);
308c26c18e4SClemens Zeidler				BAlert* alert = new BAlert(B_TRANSLATE("New Messages"),
309c26c18e4SClemens Zeidler					fAlertString.String(), "OK", NULL, NULL, B_WIDTH_AS_USUAL);
3101af4fa4bSClemens Zeidler				alert->SetFeel(B_NORMAL_WINDOW_FEEL);
311aed35104SHumdinger				alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
3121af4fa4bSClemens Zeidler				alert->Go(NULL);
3131af4fa4bSClemens Zeidler				fAlertString = B_EMPTY_STRING;
3141af4fa4bSClemens Zeidler			}
3151af4fa4bSClemens Zeidler
3161af4fa4bSClemens Zeidler			if (fCentralBeep) {
3171af4fa4bSClemens Zeidler				system_beep("New E-mail");
3181af4fa4bSClemens Zeidler				fCentralBeep = false;
3191af4fa4bSClemens Zeidler			}
3201af4fa4bSClemens Zeidler			break;
3211af4fa4bSClemens Zeidler		}
3221af4fa4bSClemens Zeidler
3231af4fa4bSClemens Zeidler		case 'mcbp':
3241af4fa4bSClemens Zeidler			if (fNewMessages > 0)
3251af4fa4bSClemens Zeidler				fCentralBeep = true;
3261af4fa4bSClemens Zeidler			break;
3271af4fa4bSClemens Zeidler
3281af4fa4bSClemens Zeidler		case kMsgCountNewMessages:	// Number of new messages
3291af4fa4bSClemens Zeidler		{
3301af4fa4bSClemens Zeidler			BMessage reply('mnuc');	// Mail New message Count
3311af4fa4bSClemens Zeidler			if (msg->FindBool("wait_for_fetch_done")) {
3321af4fa4bSClemens Zeidler				fFetchDoneRespondents.AddItem(DetachCurrentMessage());
3331af4fa4bSClemens Zeidler				break;
3341af4fa4bSClemens Zeidler			}
3351af4fa4bSClemens Zeidler
3361af4fa4bSClemens Zeidler			reply.AddInt32("num_new_messages", fNewMessages);
3371af4fa4bSClemens Zeidler			msg->SendReply(&reply);
3381af4fa4bSClemens Zeidler			break;
3391af4fa4bSClemens Zeidler		}
3401af4fa4bSClemens Zeidler
3411af4fa4bSClemens Zeidler		case 'mblk':	// Mail Blink
3421af4fa4bSClemens Zeidler			if (fNewMessages > 0)
3431af4fa4bSClemens Zeidler				fLEDAnimation->Start();
3441af4fa4bSClemens Zeidler			break;
3451af4fa4bSClemens Zeidler
3461af4fa4bSClemens Zeidler		case 'enda':	// End Auto Check
3471af4fa4bSClemens Zeidler			delete fAutoCheckRunner;
3481af4fa4bSClemens Zeidler			fAutoCheckRunner = NULL;
3491af4fa4bSClemens Zeidler			break;
3501af4fa4bSClemens Zeidler
3511af4fa4bSClemens Zeidler		case 'numg':
3521af4fa4bSClemens Zeidler		{
3537457ccb4SAugustin Cavalier			static BStringFormat format(B_TRANSLATE("{0, plural, "
354961fdd8cSAdrien Destugues				"one{# new message} other{# new messages}} for %name\n"));
3551af4fa4bSClemens Zeidler
356961fdd8cSAdrien Destugues			int32 numMessages = msg->FindInt32("num_messages");
357961fdd8cSAdrien Destugues			fAlertString.Truncate(0);
358961fdd8cSAdrien Destugues			format.Format(fAlertString, numMessages);
3598a26696cSClemens Zeidler			fAlertString.ReplaceFirst("%name", msg->FindString("name"));
3601af4fa4bSClemens Zeidler			break;
3611af4fa4bSClemens Zeidler		}
3621af4fa4bSClemens Zeidler
3631af4fa4bSClemens Zeidler		case B_QUERY_UPDATE:
3641af4fa4bSClemens Zeidler		{
36530ac5550SAxel Dörfler			int32 previousCount = fNewMessages;
36630ac5550SAxel Dörfler
36730ac5550SAxel Dörfler			int32 opcode = msg->GetInt32("opcode", -1);
36830ac5550SAxel Dörfler			switch (opcode) {
3691af4fa4bSClemens Zeidler				case B_ENTRY_CREATED:
3701af4fa4bSClemens Zeidler					fNewMessages++;
3711af4fa4bSClemens Zeidler					break;
3721af4fa4bSClemens Zeidler				case B_ENTRY_REMOVED:
3731af4fa4bSClemens Zeidler					fNewMessages--;
3741af4fa4bSClemens Zeidler					break;
37530ac5550SAxel Dörfler				default:
37630ac5550SAxel Dörfler					return;
3771af4fa4bSClemens Zeidler			}
3781af4fa4bSClemens Zeidler
3798705e1f6SAxel Dörfler			_UpdateNewMessagesNotification();
3801af4fa4bSClemens Zeidler
3810b90f99bSAdrien Destugues			if (fSettingsFile.ShowStatusWindow()
38230ac5550SAxel Dörfler					!= B_MAIL_SHOW_STATUS_WINDOW_NEVER
38330ac5550SAxel Dörfler				&& previousCount < fNewMessages) {
3844ec6c3a0SAdrien Destugues				fNotification->Send();
38530ac5550SAxel Dörfler			}
3861af4fa4bSClemens Zeidler			break;
3871af4fa4bSClemens Zeidler		}
3881af4fa4bSClemens Zeidler
3891af4fa4bSClemens Zeidler		default:
3901af4fa4bSClemens Zeidler			BApplication::MessageReceived(msg);
3911af4fa4bSClemens Zeidler			break;
3921af4fa4bSClemens Zeidler	}
3931af4fa4bSClemens Zeidler}
3941af4fa4bSClemens Zeidler
3951af4fa4bSClemens Zeidler
396d396412dSAxel Dörflervoid
397daf972c9SAxel DörflerMailDaemonApplication::Pulse()
398d396412dSAxel Dörfler{
399d396412dSAxel Dörfler	bigtime_t idle = idle_time();
400d396412dSAxel Dörfler	if (fLEDAnimation->IsRunning() && idle < 100000)
401d396412dSAxel Dörfler		fLEDAnimation->Stop();
402d396412dSAxel Dörfler}
403d396412dSAxel Dörfler
404d396412dSAxel Dörfler
405d396412dSAxel Dörflerbool
406daf972c9SAxel DörflerMailDaemonApplication::QuitRequested()
407d396412dSAxel Dörfler{
408d396412dSAxel Dörfler	RemoveDeskbarIcon();
409d396412dSAxel Dörfler	return true;
410d396412dSAxel Dörfler}
411d396412dSAxel Dörfler
412d396412dSAxel Dörfler
4131af4fa4bSClemens Zeidlervoid
414daf972c9SAxel DörflerMailDaemonApplication::InstallDeskbarIcon()
4151af4fa4bSClemens Zeidler{
4161af4fa4bSClemens Zeidler	BDeskbar deskbar;
4171af4fa4bSClemens Zeidler
4181af4fa4bSClemens Zeidler	if (!deskbar.HasItem("mail_daemon")) {
4191af4fa4bSClemens Zeidler		BRoster roster;
4201af4fa4bSClemens Zeidler		entry_ref ref;
4211af4fa4bSClemens Zeidler
422e039afe8SFrançois Revol		status_t status = roster.FindApp(B_MAIL_DAEMON_SIGNATURE, &ref);
4231af4fa4bSClemens Zeidler		if (status < B_OK) {
4241af4fa4bSClemens Zeidler			fprintf(stderr, "Can't find application to tell deskbar: %s\n",
4251af4fa4bSClemens Zeidler				strerror(status));
4261af4fa4bSClemens Zeidler			return;
4271af4fa4bSClemens Zeidler		}
4281af4fa4bSClemens Zeidler
4291af4fa4bSClemens Zeidler		status = deskbar.AddItem(&ref);
4301af4fa4bSClemens Zeidler		if (status < B_OK) {
43120537ad0SAxel Dörfler			fprintf(stderr, "Can't add deskbar replicant: %s\n",
43220537ad0SAxel Dörfler				strerror(status));
4331af4fa4bSClemens Zeidler			return;
4341af4fa4bSClemens Zeidler		}
4351af4fa4bSClemens Zeidler	}
4361af4fa4bSClemens Zeidler}
4371af4fa4bSClemens Zeidler
4381af4fa4bSClemens Zeidler
4391af4fa4bSClemens Zeidlervoid
440daf972c9SAxel DörflerMailDaemonApplication::RemoveDeskbarIcon()
4411af4fa4bSClemens Zeidler{
4421af4fa4bSClemens Zeidler	BDeskbar deskbar;
4431af4fa4bSClemens Zeidler	if (deskbar.HasItem("mail_daemon"))
4441af4fa4bSClemens Zeidler		deskbar.RemoveItem("mail_daemon");
4451af4fa4bSClemens Zeidler}
4461af4fa4bSClemens Zeidler
4471af4fa4bSClemens Zeidler
4481af4fa4bSClemens Zeidlervoid
449daf972c9SAxel DörflerMailDaemonApplication::GetNewMessages(BMessage* msg)
4501af4fa4bSClemens Zeidler{
4511af4fa4bSClemens Zeidler	int32 account = -1;
4521af4fa4bSClemens Zeidler	if (msg->FindInt32("account", &account) == B_OK && account >= 0) {
453146357b5SAxel Dörfler		// Check the single requested account
454146357b5SAxel Dörfler		BInboundMailProtocol* protocol = _InboundProtocol(account);
4553692fd58SAxel Dörfler		if (protocol != NULL)
456146357b5SAxel Dörfler			InboundMessenger(protocol).SynchronizeMessages();
4571af4fa4bSClemens Zeidler		return;
4581af4fa4bSClemens Zeidler	}
4591af4fa4bSClemens Zeidler
460146357b5SAxel Dörfler	// Check all accounts
461146357b5SAxel Dörfler
462146357b5SAxel Dörfler	AccountMap::const_iterator iterator = fAccounts.begin();
463146357b5SAxel Dörfler	for (; iterator != fAccounts.end(); iterator++) {
464146357b5SAxel Dörfler		BInboundMailProtocol* protocol = iterator->second.inboundProtocol;
4653692fd58SAxel Dörfler		if (protocol != NULL)
466146357b5SAxel Dörfler			InboundMessenger(protocol).SynchronizeMessages();
4671af4fa4bSClemens Zeidler	}
4681af4fa4bSClemens Zeidler}
4691af4fa4bSClemens Zeidler
4701af4fa4bSClemens Zeidler
4711af4fa4bSClemens Zeidlervoid
472daf972c9SAxel DörflerMailDaemonApplication::SendPendingMessages(BMessage* msg)
4731af4fa4bSClemens Zeidler{
474d396412dSAxel Dörfler	BVolumeRoster roster;
475d396412dSAxel Dörfler	BVolume volume;
476146357b5SAxel Dörfler	std::map<int32, send_mails_info> messages;
47762eec600SAxel Dörfler	int32 account = msg->GetInt32("account", -1);
4781af4fa4bSClemens Zeidler
4791af4fa4bSClemens Zeidler	if (!msg->HasString("message_path")) {
4801af4fa4bSClemens Zeidler		while (roster.GetNextVolume(&volume) == B_OK) {
4811af4fa4bSClemens Zeidler			BQuery query;
4821af4fa4bSClemens Zeidler			query.SetVolume(&volume);
4831af4fa4bSClemens Zeidler			query.PushAttr(B_MAIL_ATTR_FLAGS);
4841af4fa4bSClemens Zeidler			query.PushInt32(B_MAIL_PENDING);
4851af4fa4bSClemens Zeidler			query.PushOp(B_EQ);
4861af4fa4bSClemens Zeidler
4871af4fa4bSClemens Zeidler			query.PushAttr(B_MAIL_ATTR_FLAGS);
4881af4fa4bSClemens Zeidler			query.PushInt32(B_MAIL_PENDING | B_MAIL_SAVE);
4891af4fa4bSClemens Zeidler			query.PushOp(B_EQ);
4901af4fa4bSClemens Zeidler
4911af4fa4bSClemens Zeidler			if (account >= 0) {
492a64bd564SClemens Zeidler				query.PushAttr(B_MAIL_ATTR_ACCOUNT_ID);
4931af4fa4bSClemens Zeidler				query.PushInt32(account);
4941af4fa4bSClemens Zeidler				query.PushOp(B_EQ);
4951af4fa4bSClemens Zeidler				query.PushOp(B_AND);
4961af4fa4bSClemens Zeidler			}
4971af4fa4bSClemens Zeidler
4981af4fa4bSClemens Zeidler			query.PushOp(B_OR);
4991af4fa4bSClemens Zeidler			query.Fetch();
5001af4fa4bSClemens Zeidler			BEntry entry;
5011af4fa4bSClemens Zeidler			while (query.GetNextEntry(&entry) == B_OK) {
5021af4fa4bSClemens Zeidler				if (_IsEntryInTrash(entry))
5031af4fa4bSClemens Zeidler					continue;
5041af4fa4bSClemens Zeidler
5051af4fa4bSClemens Zeidler				BNode node;
5061af4fa4bSClemens Zeidler				while (node.SetTo(&entry) == B_BUSY)
5071af4fa4bSClemens Zeidler					snooze(1000);
5081af4fa4bSClemens Zeidler				if (!_IsPending(node))
5091af4fa4bSClemens Zeidler					continue;
5101af4fa4bSClemens Zeidler
511a64bd564SClemens Zeidler				if (node.ReadAttr(B_MAIL_ATTR_ACCOUNT_ID, B_INT32_TYPE, 0,
512146357b5SAxel Dörfler						&account, sizeof(int32)) < 0)
513146357b5SAxel Dörfler					account = -1;
5141af4fa4bSClemens Zeidler
515146357b5SAxel Dörfler				_AddMessage(messages[account], entry, node);
5161af4fa4bSClemens Zeidler			}
5171af4fa4bSClemens Zeidler		}
5181af4fa4bSClemens Zeidler	} else {
519146357b5SAxel Dörfler		// Send the requested message only
5201af4fa4bSClemens Zeidler		const char* path;
5211af4fa4bSClemens Zeidler		if (msg->FindString("message_path", &path) != B_OK)
5221af4fa4bSClemens Zeidler			return;
5231af4fa4bSClemens Zeidler
5241af4fa4bSClemens Zeidler		BEntry entry(path);
525146357b5SAxel Dörfler		_AddMessage(messages[account], entry, BNode(&entry));
5261af4fa4bSClemens Zeidler	}
5271af4fa4bSClemens Zeidler
528146357b5SAxel Dörfler	std::map<int32, send_mails_info>::iterator iterator = messages.begin();
529146357b5SAxel Dörfler	for (; iterator != messages.end(); iterator++) {
530146357b5SAxel Dörfler		BOutboundMailProtocol* protocol = _OutboundProtocol(iterator->first);
531146357b5SAxel Dörfler		if (protocol == NULL)
5321af4fa4bSClemens Zeidler			continue;
5331af4fa4bSClemens Zeidler
534146357b5SAxel Dörfler		send_mails_info& info = iterator->second;
535146357b5SAxel Dörfler		if (info.bytes == 0)
5361af4fa4bSClemens Zeidler			continue;
5371af4fa4bSClemens Zeidler
53862eec600SAxel Dörfler		protocol->SendMessages(info.files, info.bytes);
5391af4fa4bSClemens Zeidler	}
540d396412dSAxel Dörfler}
541d396412dSAxel Dörfler
5421af4fa4bSClemens Zeidler
543d396412dSAxel Dörflervoid
544daf972c9SAxel DörflerMailDaemonApplication::MakeMimeTypes(bool remakeMIMETypes)
545d396412dSAxel Dörfler{
546d396412dSAxel Dörfler	// Add MIME database entries for the e-mail file types we handle.  Either
547d396412dSAxel Dörfler	// do a full rebuild from nothing, or just add on the new attributes that
548d396412dSAxel Dörfler	// we support which the regular BeOS mail daemon didn't have.
549d396412dSAxel Dörfler
550d396412dSAxel Dörfler	const uint8 kNTypes = 2;
551d396412dSAxel Dörfler	const char* types[kNTypes] = {"text/x-email", "text/x-partial-email"};
552d396412dSAxel Dörfler
553d396412dSAxel Dörfler	for (size_t i = 0; i < kNTypes; i++) {
554d396412dSAxel Dörfler		BMessage info;
555d396412dSAxel Dörfler		BMimeType mime(types[i]);
556d396412dSAxel Dörfler		if (mime.InitCheck() != B_OK) {
557d396412dSAxel Dörfler			fputs("could not init mime type.\n", stderr);
558d396412dSAxel Dörfler			return;
559d396412dSAxel Dörfler		}
560d396412dSAxel Dörfler
561d396412dSAxel Dörfler		if (!mime.IsInstalled() || remakeMIMETypes) {
562d396412dSAxel Dörfler			// install the full mime type
563d396412dSAxel Dörfler			mime.Delete();
564d396412dSAxel Dörfler			mime.Install();
565d396412dSAxel Dörfler
566d396412dSAxel Dörfler			// Set up the list of e-mail related attributes that Tracker will
567d396412dSAxel Dörfler			// let you display in columns for e-mail messages.
568d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_NAME, "Name");
569d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_SUBJECT, "Subject");
570d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_TO, "To");
571d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_CC, "Cc");
572d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_FROM, "From");
573d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_REPLY, "Reply To");
574d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_STATUS, "Status");
575d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_PRIORITY, "Priority", B_STRING_TYPE,
576d396412dSAxel Dörfler				true, true, 40);
577d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_WHEN, "When", B_TIME_TYPE, true,
578d396412dSAxel Dörfler				false, 150);
579d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_THREAD, "Thread");
580d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_ACCOUNT, "Account", B_STRING_TYPE,
581d396412dSAxel Dörfler				true, false, 100);
582d396412dSAxel Dörfler			addAttribute(info, B_MAIL_ATTR_READ, "Read", B_INT32_TYPE,
583d396412dSAxel Dörfler				true, false, 70);
584d396412dSAxel Dörfler			mime.SetAttrInfo(&info);
585d396412dSAxel Dörfler
586d396412dSAxel Dörfler			if (i == 0) {
587d396412dSAxel Dörfler				mime.SetShortDescription("E-mail");
588d396412dSAxel Dörfler				mime.SetLongDescription("Electronic Mail Message");
589d396412dSAxel Dörfler				mime.SetPreferredApp("application/x-vnd.Be-MAIL");
590d396412dSAxel Dörfler			} else {
591d396412dSAxel Dörfler				mime.SetShortDescription("Partial E-mail");
592d396412dSAxel Dörfler				mime.SetLongDescription("A Partially Downloaded E-mail");
593d396412dSAxel Dörfler				mime.SetPreferredApp("application/x-vnd.Be-MAIL");
594d396412dSAxel Dörfler			}
595d396412dSAxel Dörfler		}
596d396412dSAxel Dörfler	}
5971af4fa4bSClemens Zeidler}
5981af4fa4bSClemens Zeidler
5991af4fa4bSClemens Zeidler
6001af4fa4bSClemens Zeidlervoid
601daf972c9SAxel DörflerMailDaemonApplication::_InitAccounts()
6021af4fa4bSClemens Zeidler{
603d396412dSAxel Dörfler	BMailAccounts accounts;
604d396412dSAxel Dörfler	for (int i = 0; i < accounts.CountAccounts(); i++)
605d396412dSAxel Dörfler		_InitAccount(*accounts.AccountAt(i));
606d396412dSAxel Dörfler}
607d396412dSAxel Dörfler
608d396412dSAxel Dörfler
609d396412dSAxel Dörflervoid
610daf972c9SAxel DörflerMailDaemonApplication::_InitAccount(BMailAccountSettings& settings)
611d396412dSAxel Dörfler{
612d396412dSAxel Dörfler	account_protocols account;
613146357b5SAxel Dörfler
614d396412dSAxel Dörfler	// inbound
615d396412dSAxel Dörfler	if (settings.IsInboundEnabled()) {
616d396412dSAxel Dörfler		account.inboundProtocol = _CreateInboundProtocol(settings,
617d396412dSAxel Dörfler			account.inboundImage);
618d396412dSAxel Dörfler	}
619146357b5SAxel Dörfler	if (account.inboundProtocol != NULL) {
620d396412dSAxel Dörfler		DefaultNotifier* notifier = new DefaultNotifier(settings.Name(), true,
6210b90f99bSAdrien Destugues			fErrorLogWindow, fSettingsFile.ShowStatusWindow());
622d396412dSAxel Dörfler		account.inboundProtocol->SetMailNotifier(notifier);
623146357b5SAxel Dörfler		account.inboundProtocol->Run();
624d396412dSAxel Dörfler	}
625d396412dSAxel Dörfler
626d396412dSAxel Dörfler	// outbound
627d396412dSAxel Dörfler	if (settings.IsOutboundEnabled()) {
628d396412dSAxel Dörfler		account.outboundProtocol = _CreateOutboundProtocol(settings,
629d396412dSAxel Dörfler			account.outboundImage);
630d396412dSAxel Dörfler	}
631146357b5SAxel Dörfler	if (account.outboundProtocol != NULL) {
632d396412dSAxel Dörfler		DefaultNotifier* notifier = new DefaultNotifier(settings.Name(), false,
6330b90f99bSAdrien Destugues			fErrorLogWindow, fSettingsFile.ShowStatusWindow());
634d396412dSAxel Dörfler		account.outboundProtocol->SetMailNotifier(notifier);
635146357b5SAxel Dörfler		account.outboundProtocol->Run();
636d396412dSAxel Dörfler	}
637d396412dSAxel Dörfler
638d396412dSAxel Dörfler	printf("account name %s, id %i, in %p, out %p\n", settings.Name(),
639d396412dSAxel Dörfler		(int)settings.AccountID(), account.inboundProtocol,
640d396412dSAxel Dörfler		account.outboundProtocol);
641d396412dSAxel Dörfler
642146357b5SAxel Dörfler	if (account.inboundProtocol != NULL || account.outboundProtocol != NULL)
643146357b5SAxel Dörfler		fAccounts[settings.AccountID()] = account;
644146357b5SAxel Dörfler}
645d396412dSAxel Dörfler
646d396412dSAxel Dörfler
647d396412dSAxel Dörflervoid
648daf972c9SAxel DörflerMailDaemonApplication::_ReloadAccounts(BMessage* message)
649d396412dSAxel Dörfler{
650d396412dSAxel Dörfler	type_code typeFound;
651d396412dSAxel Dörfler	int32 countFound;
652d396412dSAxel Dörfler	message->GetInfo("account", &typeFound, &countFound);
653d396412dSAxel Dörfler	if (typeFound != B_INT32_TYPE)
654d396412dSAxel Dörfler		return;
655d396412dSAxel Dörfler
656d396412dSAxel Dörfler	// reload accounts
657d396412dSAxel Dörfler	BMailAccounts accounts;
658d396412dSAxel Dörfler
659d396412dSAxel Dörfler	for (int i = 0; i < countFound; i++) {
660d396412dSAxel Dörfler		int32 account = message->FindInt32("account", i);
661146357b5SAxel Dörfler		AccountMap::iterator found = fAccounts.find(account);
662146357b5SAxel Dörfler		if (found != fAccounts.end()) {
663146357b5SAxel Dörfler			_RemoveAccount(found->second);
664146357b5SAxel Dörfler			fAccounts.erase(found);
665146357b5SAxel Dörfler		}
666146357b5SAxel Dörfler
667d396412dSAxel Dörfler		BMailAccountSettings* settings = accounts.AccountByID(account);
66820537ad0SAxel Dörfler		if (settings != NULL)
669d396412dSAxel Dörfler			_InitAccount(*settings);
670d396412dSAxel Dörfler	}
671d396412dSAxel Dörfler}
672d396412dSAxel Dörfler
673d396412dSAxel Dörfler
674d396412dSAxel Dörflervoid
675daf972c9SAxel DörflerMailDaemonApplication::_RemoveAccount(const account_protocols& account)
676d396412dSAxel Dörfler{
677146357b5SAxel Dörfler	if (account.inboundProtocol != NULL) {
678146357b5SAxel Dörfler		account.inboundProtocol->Lock();
679146357b5SAxel Dörfler		account.inboundProtocol->Quit();
680146357b5SAxel Dörfler
681146357b5SAxel Dörfler		unload_add_on(account.inboundImage);
682d396412dSAxel Dörfler	}
683146357b5SAxel Dörfler
684146357b5SAxel Dörfler	if (account.outboundProtocol != NULL) {
685146357b5SAxel Dörfler		account.outboundProtocol->Lock();
686146357b5SAxel Dörfler		account.outboundProtocol->Quit();
687146357b5SAxel Dörfler
688146357b5SAxel Dörfler		unload_add_on(account.outboundImage);
689d396412dSAxel Dörfler	}
690d396412dSAxel Dörfler}
691d396412dSAxel Dörfler
692d396412dSAxel Dörfler
693146357b5SAxel DörflerBInboundMailProtocol*
694daf972c9SAxel DörflerMailDaemonApplication::_CreateInboundProtocol(BMailAccountSettings& settings,
695d396412dSAxel Dörfler	image_id& image)
696d396412dSAxel Dörfler{
697146357b5SAxel Dörfler	const entry_ref& entry = settings.InboundAddOnRef();
698146357b5SAxel Dörfler	BInboundMailProtocol* (*instantiateProtocol)(BMailAccountSettings*);
699d396412dSAxel Dörfler
700d396412dSAxel Dörfler	BPath path(&entry);
701d396412dSAxel Dörfler	image = load_add_on(path.Path());
702d396412dSAxel Dörfler	if (image < 0)
703d396412dSAxel Dörfler		return NULL;
704146357b5SAxel Dörfler
705d396412dSAxel Dörfler	if (get_image_symbol(image, "instantiate_inbound_protocol",
706146357b5SAxel Dörfler			B_SYMBOL_TYPE_TEXT, (void**)&instantiateProtocol) != B_OK) {
707d396412dSAxel Dörfler		unload_add_on(image);
708d396412dSAxel Dörfler		image = -1;
709d396412dSAxel Dörfler		return NULL;
710d396412dSAxel Dörfler	}
711146357b5SAxel Dörfler	return instantiateProtocol(&settings);
712d396412dSAxel Dörfler}
713d396412dSAxel Dörfler
714d396412dSAxel Dörfler
715146357b5SAxel DörflerBOutboundMailProtocol*
716daf972c9SAxel DörflerMailDaemonApplication::_CreateOutboundProtocol(BMailAccountSettings& settings,
717d396412dSAxel Dörfler	image_id& image)
718d396412dSAxel Dörfler{
719146357b5SAxel Dörfler	const entry_ref& entry = settings.OutboundAddOnRef();
720146357b5SAxel Dörfler	BOutboundMailProtocol* (*instantiateProtocol)(BMailAccountSettings*);
721d396412dSAxel Dörfler
722d396412dSAxel Dörfler	BPath path(&entry);
723d396412dSAxel Dörfler	image = load_add_on(path.Path());
724d396412dSAxel Dörfler	if (image < 0)
725d396412dSAxel Dörfler		return NULL;
726146357b5SAxel Dörfler
727d396412dSAxel Dörfler	if (get_image_symbol(image, "instantiate_outbound_protocol",
728146357b5SAxel Dörfler			B_SYMBOL_TYPE_TEXT, (void**)&instantiateProtocol) != B_OK) {
729d396412dSAxel Dörfler		unload_add_on(image);
730d396412dSAxel Dörfler		image = -1;
731d396412dSAxel Dörfler		return NULL;
732d396412dSAxel Dörfler	}
733146357b5SAxel Dörfler	return instantiateProtocol(&settings);
734d396412dSAxel Dörfler}
735d396412dSAxel Dörfler
736d396412dSAxel Dörfler
737146357b5SAxel DörflerBInboundMailProtocol*
738daf972c9SAxel DörflerMailDaemonApplication::_InboundProtocol(int32 account)
739d396412dSAxel Dörfler{
740146357b5SAxel Dörfler	AccountMap::iterator found = fAccounts.find(account);
741146357b5SAxel Dörfler	if (found == fAccounts.end())
742d396412dSAxel Dörfler		return NULL;
743146357b5SAxel Dörfler	return found->second.inboundProtocol;
744d396412dSAxel Dörfler}
745d396412dSAxel Dörfler
746d396412dSAxel Dörfler
747146357b5SAxel DörflerBOutboundMailProtocol*
748daf972c9SAxel DörflerMailDaemonApplication::_OutboundProtocol(int32 account)
749d396412dSAxel Dörfler{
750d396412dSAxel Dörfler	if (account < 0)
751d396412dSAxel Dörfler		account = BMailSettings().DefaultOutboundAccount();
752d396412dSAxel Dörfler
753146357b5SAxel Dörfler	AccountMap::iterator found = fAccounts.find(account);
754146357b5SAxel Dörfler	if (found == fAccounts.end())
755d396412dSAxel Dörfler		return NULL;
756146357b5SAxel Dörfler	return found->second.outboundProtocol;
757d396412dSAxel Dörfler}
758d396412dSAxel Dörfler
759d396412dSAxel Dörfler
760d396412dSAxel Dörflervoid
7618705e1f6SAxel DörflerMailDaemonApplication::_InitNewMessagesCount()
7628705e1f6SAxel Dörfler{
7638705e1f6SAxel Dörfler	BVolume volume;
7648705e1f6SAxel Dörfler	BVolumeRoster roster;
7658705e1f6SAxel Dörfler
7668705e1f6SAxel Dörfler	fNewMessages = 0;
7678705e1f6SAxel Dörfler
7688705e1f6SAxel Dörfler	while (roster.GetNextVolume(&volume) == B_OK) {
7698705e1f6SAxel Dörfler		BQuery* query = new BQuery;
7708705e1f6SAxel Dörfler
7718705e1f6SAxel Dörfler		query->SetTarget(this);
7728705e1f6SAxel Dörfler		query->SetVolume(&volume);
7738705e1f6SAxel Dörfler		query->PushAttr(B_MAIL_ATTR_STATUS);
7748705e1f6SAxel Dörfler		query->PushString("New");
7758705e1f6SAxel Dörfler		query->PushOp(B_EQ);
7768705e1f6SAxel Dörfler		query->PushAttr("BEOS:TYPE");
7778705e1f6SAxel Dörfler		query->PushString("text/x-email");
7788705e1f6SAxel Dörfler		query->PushOp(B_EQ);
7798705e1f6SAxel Dörfler		query->PushAttr("BEOS:TYPE");
7808705e1f6SAxel Dörfler		query->PushString("text/x-partial-email");
7818705e1f6SAxel Dörfler		query->PushOp(B_EQ);
7828705e1f6SAxel Dörfler		query->PushOp(B_OR);
7838705e1f6SAxel Dörfler		query->PushOp(B_AND);
7848705e1f6SAxel Dörfler		query->Fetch();
7858705e1f6SAxel Dörfler
7868705e1f6SAxel Dörfler		BEntry entry;
7878705e1f6SAxel Dörfler		while (query->GetNextEntry(&entry) == B_OK)
7888705e1f6SAxel Dörfler			fNewMessages++;
7898705e1f6SAxel Dörfler
7908705e1f6SAxel Dörfler		fQueries.AddItem(query);
7918705e1f6SAxel Dörfler	}
7928705e1f6SAxel Dörfler}
7938705e1f6SAxel Dörfler
7948705e1f6SAxel Dörfler
7958705e1f6SAxel Dörflervoid
7968705e1f6SAxel DörflerMailDaemonApplication::_UpdateNewMessagesNotification()
7978705e1f6SAxel Dörfler{
7988705e1f6SAxel Dörfler	BString title;
7998705e1f6SAxel Dörfler	if (fNewMessages > 0) {
8007457ccb4SAugustin Cavalier		BStringFormat format(B_TRANSLATE(
8018705e1f6SAxel Dörfler			"{0, plural, one{One new message} other{# new messages}}"));
8028705e1f6SAxel Dörfler
8038705e1f6SAxel Dörfler		format.Format(title, fNewMessages);
8048705e1f6SAxel Dörfler	} else
8058705e1f6SAxel Dörfler		title = B_TRANSLATE("No new messages");
8068705e1f6SAxel Dörfler
8078705e1f6SAxel Dörfler	fNotification->SetTitle(title.String());
8088705e1f6SAxel Dörfler}
8098705e1f6SAxel Dörfler
8108705e1f6SAxel Dörfler
8118705e1f6SAxel Dörflervoid
8128705e1f6SAxel DörflerMailDaemonApplication::_UpdateAutoCheckRunner()
813d396412dSAxel Dörfler{
8148705e1f6SAxel Dörfler	bigtime_t interval = fSettingsFile.AutoCheckInterval();
815d396412dSAxel Dörfler	if (interval > 0) {
816d396412dSAxel Dörfler		if (fAutoCheckRunner != NULL) {
817d396412dSAxel Dörfler			fAutoCheckRunner->SetInterval(interval);
818d396412dSAxel Dörfler			fAutoCheckRunner->SetCount(-1);
81920537ad0SAxel Dörfler		} else {
8204cab719fSAxel Dörfler			BMessage update(kMsgAutoCheck);
8214cab719fSAxel Dörfler			fAutoCheckRunner = new BMessageRunner(be_app_messenger, &update,
8224cab719fSAxel Dörfler				interval);
8234cab719fSAxel Dörfler
8244cab719fSAxel Dörfler			// Send one right away -- the message runner will wait until the
8254cab719fSAxel Dörfler			// first interval has passed before sending a message
8264cab719fSAxel Dörfler			PostMessage(&update);
82720537ad0SAxel Dörfler		}
828d396412dSAxel Dörfler	} else {
829d396412dSAxel Dörfler		delete fAutoCheckRunner;
830d396412dSAxel Dörfler		fAutoCheckRunner = NULL;
831d396412dSAxel Dörfler	}
8321af4fa4bSClemens Zeidler}
8331af4fa4bSClemens Zeidler
8341af4fa4bSClemens Zeidler
835146357b5SAxel Dörflervoid
836daf972c9SAxel DörflerMailDaemonApplication::_AddMessage(send_mails_info& info, const BEntry& entry,
837146357b5SAxel Dörfler	const BNode& node)
838146357b5SAxel Dörfler{
839146357b5SAxel Dörfler	entry_ref ref;
840146357b5SAxel Dörfler	off_t size;
841146357b5SAxel Dörfler	if (node.GetSize(&size) == B_OK && entry.GetRef(&ref) == B_OK) {
842146357b5SAxel Dörfler		info.files.AddRef("ref", &ref);
843146357b5SAxel Dörfler		info.bytes += size;
844146357b5SAxel Dörfler	}
845146357b5SAxel Dörfler}
846146357b5SAxel Dörfler
847146357b5SAxel Dörfler
8481af4fa4bSClemens Zeidler/*!	Work-around for a broken index that contains out-of-date information.
8491af4fa4bSClemens Zeidler*/
850d396412dSAxel Dörfler/*static*/ bool
851daf972c9SAxel DörflerMailDaemonApplication::_IsPending(BNode& node)
8521af4fa4bSClemens Zeidler{
8531af4fa4bSClemens Zeidler	int32 flags;
8541af4fa4bSClemens Zeidler	if (node.ReadAttr(B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0, &flags, sizeof(int32))
8551af4fa4bSClemens Zeidler			!= (ssize_t)sizeof(int32))
8561af4fa4bSClemens Zeidler		return false;
8571af4fa4bSClemens Zeidler
8581af4fa4bSClemens Zeidler	return (flags & B_MAIL_PENDING) != 0;
8591af4fa4bSClemens Zeidler}
8601af4fa4bSClemens Zeidler
8611af4fa4bSClemens Zeidler
862d396412dSAxel Dörfler/*static*/ bool
863daf972c9SAxel DörflerMailDaemonApplication::_IsEntryInTrash(BEntry& entry)
8641af4fa4bSClemens Zeidler{
8651af4fa4bSClemens Zeidler	entry_ref ref;
8661af4fa4bSClemens Zeidler	entry.GetRef(&ref);
8671af4fa4bSClemens Zeidler
8681af4fa4bSClemens Zeidler	BVolume volume(ref.device);
8691af4fa4bSClemens Zeidler	BPath path;
8701af4fa4bSClemens Zeidler	if (volume.InitCheck() != B_OK
8711af4fa4bSClemens Zeidler		|| find_directory(B_TRASH_DIRECTORY, &path, false, &volume) != B_OK)
8721af4fa4bSClemens Zeidler		return false;
8731af4fa4bSClemens Zeidler
8741af4fa4bSClemens Zeidler	BDirectory trash(path.Path());
8751af4fa4bSClemens Zeidler	return trash.Contains(&entry);
8761af4fa4bSClemens Zeidler}
877