cvsimport
[beagle.git] / beagled / EvolutionMailDriver / EvolutionMailDriver.cs
blob18bba3ce76b53a6c13718c8b2df0fa8c3ccccb3b
1 //
2 // EvolutionMailDriver.cs
3 //
4 // Copyright (C) 2004 Novell, Inc.
5 //
6 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
28 using System;
29 using System.Collections;
30 using System.IO;
31 using System.Threading;
33 using Beagle.Util;
34 using Camel = Beagle.Util.Camel;
36 namespace Beagle.Daemon.EvolutionMailDriver {
38 [QueryableFlavor (Name="EvolutionMail", Domain=QueryDomain.Local, RequireInotify=false)]
39 public class EvolutionMailQueryable : LuceneQueryable {
41 public int polling_interval_in_seconds = 60;
43 private string local_path, imap_path, imap4_path;
45 private MailCrawler crawler;
47 private ArrayList running_generators = new ArrayList ();
49 // Index versions
50 // 1: Original version, stored all recipient addresses as a
51 // RFC822 string
52 // 2: Stores recipients in separate properties,
53 // filters/indexes all attachments
54 // 3: Make email addresses non-keyword, add sanitized version
55 // for searching for parts of an email address.
56 // 4: Make the flags property mutable, and create a property
57 // change Indexable when they change for IMAP generators.
58 // 5: No need for a separate sanitized version of email addresses.
59 private const int INDEX_VERSION = 5;
61 public EvolutionMailQueryable () : base ("EvolutionMailIndex", INDEX_VERSION)
63 this.local_path = Path.Combine (PathFinder.HomeDir, ".evolution/mail/local");
64 this.imap_path = Path.Combine (PathFinder.HomeDir, ".evolution/mail/imap");
65 this.imap4_path = Path.Combine (PathFinder.HomeDir, ".evolution/mail/imap4");
68 private void CrawlHook (Scheduler.Task task)
70 crawler.Crawl ();
71 task.Reschedule = true;
72 task.TriggerTime = DateTime.Now.AddSeconds (polling_interval_in_seconds);
75 //////////////////////////////////////////////////////////////////////////////////////////////
77 private void StartWorker ()
79 Logger.Log.Info ("Starting Evolution mail backend");
81 Stopwatch stopwatch = new Stopwatch ();
82 stopwatch.Start ();
84 // Check that we have data to index
85 if ((! Directory.Exists (this.local_path)) && (! Directory.Exists (this.imap_path))) {
86 // No mails present, repoll every minute
87 Logger.Log.Warn ("Evolution mail store not found, watching for it.");
88 GLib.Timeout.Add (60000, new GLib.TimeoutHandler (CheckForMailData));
89 return;
92 Logger.Log.Debug ("Starting mail crawl");
93 crawler = new MailCrawler (this.local_path, this.imap_path, this.imap4_path);
94 crawler.MboxAddedEvent += IndexMbox;
95 crawler.SummaryAddedEvent += IndexSummary;
96 crawler.Crawl ();
97 Logger.Log.Debug ("Mail crawl finished");
99 // If we don't have inotify, we have to poll the file system. Ugh.
100 if (! Inotify.Enabled) {
101 Scheduler.Task task = Scheduler.TaskFromHook (new Scheduler.TaskHook (CrawlHook));
102 task.Tag = "Crawling ~/.evolution to find summary changes";
103 task.Source = this;
104 ThisScheduler.Add (task);
107 stopwatch.Stop ();
108 Logger.Log.Info ("Evolution mail driver worker thread done in {0}",
109 stopwatch);
112 public override void Start ()
114 base.Start ();
116 ExceptionHandlingThread.Start (new ThreadStart (StartWorker));
119 private bool CheckForMailData ()
121 if ((! Directory.Exists (this.local_path)) && (! Directory.Exists (this.imap_path)))
122 return true; // continue polling
124 // Otherwise stop polling and start indexing
125 StartWorker();
126 return false;
129 public string Name {
130 get { return "EvolutionMail"; }
133 public void IndexSummary (FileInfo summaryInfo)
135 // If there's already a task running for this folder,
136 // don't interrupt it.
137 if (ThisScheduler.ContainsByTag (summaryInfo.FullName)) {
138 Logger.Log.Debug ("Not adding task for already running task: {0}", summaryInfo.FullName);
139 return;
142 Logger.Log.Debug ("Will index summary {0}", summaryInfo.FullName);
143 EvolutionMailIndexableGeneratorImap generator = new EvolutionMailIndexableGeneratorImap (this, summaryInfo);
144 Scheduler.Task task;
145 task = NewAddTask (generator);
146 task.Tag = summaryInfo.FullName;
147 ThisScheduler.Add (task);
149 AddGenerator (generator);
152 public void IndexMbox (FileInfo mboxInfo)
154 // If there's already a task running for this mbox,
155 // don't interrupt it.
156 if (ThisScheduler.ContainsByTag (mboxInfo.FullName)) {
157 Logger.Log.Debug ("Not adding task for already running task: {0}", mboxInfo.FullName);
158 return;
161 Logger.Log.Debug ("Will index mbox {0}", mboxInfo.FullName);
162 EvolutionMailIndexableGeneratorMbox generator = new EvolutionMailIndexableGeneratorMbox (this, mboxInfo);
163 Scheduler.Task task;
164 task = NewAddTask (generator);
165 task.Tag = mboxInfo.FullName;
166 ThisScheduler.Add (task);
168 AddGenerator (generator);
171 internal void AddGenerator (EvolutionMailIndexableGenerator generator)
173 running_generators.Add (generator);
176 internal void RemoveGenerator (EvolutionMailIndexableGenerator generator)
178 running_generators.Remove (generator);
181 protected override bool IsIndexing {
182 get { return running_generators.Count > 0; }
185 protected override int ProgressPercent {
186 get {
187 if (running_generators.Count == 0)
188 return -1;
190 // An embarrassingly unscientific attempt at getting progress
191 // information from the mail backend as a whole. Unfortunately
192 // the IMAP and mbox backends don't have a common unit of
193 // measurement (IMAP has number of messages, mbox number of
194 // bytes), so we can't get anything really accurate.
195 double total_percent = 0;
197 foreach (EvolutionMailIndexableGenerator generator in running_generators)
198 total_percent += generator.ProgressPercent;
200 return (int) (total_percent / running_generators.Count);
204 public static Uri EmailUri (string accountName, string folderName, string uid)
206 return new Uri (String.Format ("email://{0}/{1};uid={2}",
207 accountName, folderName, uid));