88
99import aioimaplib
1010import aiosmtplib
11- from pydantic import BaseModel
1211
1312from mcp_email_server .config import EmailServer , EmailSettings
14-
15-
16- class EmailData (BaseModel ):
17- subject : str
18- sender : str
19- body : str
20- date : datetime
21- attachments : list [str ]
22-
23- @classmethod
24- def from_email (cls , email : dict [str , Any ]):
25- return cls (
26- subject = email ["subject" ],
27- sender = email ["from" ],
28- body = email ["body" ],
29- date = email ["date" ],
30- attachments = email ["attachments" ],
31- )
32-
33-
34- class EmailPageResponse (BaseModel ):
35- page : int
36- page_size : int
37- before : datetime | None
38- after : datetime | None
39- include : str | None
40- emails : list [EmailData ]
41- total : int
13+ from mcp_email_server .emails import EmailHandler
14+ from mcp_email_server .emails .models import EmailData , EmailPageResponse
4215
4316
4417class EmailClient :
@@ -128,16 +101,20 @@ async def get_emails_stream( # noqa: C901
128101 await imap .select ("INBOX" )
129102
130103 # Build search criteria
131- search_criteria = "ALL"
104+ search_criteria = []
132105 if before :
133- search_criteria = f'( BEFORE " { before .isoformat ()} ")'
106+ search_criteria . extend ([ " BEFORE" , before .isoformat ()])
134107 if after :
135- search_criteria = f' { search_criteria } ( AFTER " { after .isoformat ()} ")'
108+ search_criteria . extend ([ " AFTER" , after .isoformat ()])
136109 if include :
137- search_criteria = f'{ search_criteria } (TEXT "{ include } ")'
110+ search_criteria .extend (["TEXT" , include ])
111+
112+ # If no specific criteria, search for ALL
113+ if not search_criteria :
114+ search_criteria = ["ALL" ]
138115
139116 # Search for messages
140- _ , messages = await imap .search (search_criteria )
117+ _ , messages = await imap .search (* search_criteria )
141118 message_ids = messages [0 ].split ()
142119 start = (page - 1 ) * page_size
143120 end = start + page_size
@@ -203,16 +180,20 @@ async def get_email_count(
203180 await imap .select ("INBOX" )
204181
205182 # Build search criteria
206- search_criteria = "ALL"
183+ search_criteria = []
207184 if before :
208- search_criteria = f'( BEFORE " { before .isoformat ()} ")'
185+ search_criteria . extend ([ " BEFORE" , before .isoformat ()])
209186 if after :
210- search_criteria = f' { search_criteria } ( AFTER " { after .isoformat ()} ")'
187+ search_criteria . extend ([ " AFTER" , after .isoformat ()])
211188 if include :
212- search_criteria = f'{ search_criteria } (TEXT "{ include } ")'
189+ search_criteria .extend (["TEXT" , include ])
190+
191+ # If no specific criteria, search for ALL
192+ if not search_criteria :
193+ search_criteria = ["ALL" ]
213194
214195 # Search for messages and count them
215- _ , messages = await imap .search (search_criteria )
196+ _ , messages = await imap .search (* search_criteria )
216197 return len (messages [0 ].split ())
217198 finally :
218199 # Ensure we logout properly
@@ -237,7 +218,7 @@ async def send_email(self, recipient: str, subject: str, body: str):
237218 await smtp .send_message (msg )
238219
239220
240- class ClassicEmailHandler :
221+ class ClassicEmailHandler ( EmailHandler ) :
241222 def __init__ (self , email_settings : EmailSettings ):
242223 self .email_settings = email_settings
243224 self .incoming_client = EmailClient (email_settings .incoming )
@@ -268,5 +249,5 @@ async def get_emails(
268249 total = total ,
269250 )
270251
271- async def send_email (self , recipient : str , subject : str , body : str ):
252+ async def send_email (self , recipient : str , subject : str , body : str ) -> None :
272253 await self .outgoing_client .send_email (recipient , subject , body )
0 commit comments