_parseaddr.py (11003B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\email\_parseaddr.py 2 __all__ = ['mktime_tz', 3 'parsedate', 4 'parsedate_tz', 5 'quote'] 6 import time 7 SPACE = ' ' 8 EMPTYSTRING = '' 9 COMMASPACE = ', ' 10 _monthnames = ['jan', 11 'feb', 12 'mar', 13 'apr', 14 'may', 15 'jun', 16 'jul', 17 'aug', 18 'sep', 19 'oct', 20 'nov', 21 'dec', 22 'january', 23 'february', 24 'march', 25 'april', 26 'may', 27 'june', 28 'july', 29 'august', 30 'september', 31 'october', 32 'november', 33 'december'] 34 _daynames = ['mon', 35 'tue', 36 'wed', 37 'thu', 38 'fri', 39 'sat', 40 'sun'] 41 _timezones = {'UT': 0, 42 'UTC': 0, 43 'GMT': 0, 44 'Z': 0, 45 'AST': -400, 46 'ADT': -300, 47 'EST': -500, 48 'EDT': -400, 49 'CST': -600, 50 'CDT': -500, 51 'MST': -700, 52 'MDT': -600, 53 'PST': -800, 54 'PDT': -700} 55 56 def parsedate_tz(data): 57 data = data.split() 58 if data[0].endswith(',') or data[0].lower() in _daynames: 59 del data[0] 60 else: 61 i = data[0].rfind(',') 62 if i >= 0: 63 data[0] = data[0][i + 1:] 64 if len(data) == 3: 65 stuff = data[0].split('-') 66 if len(stuff) == 3: 67 data = stuff + data[1:] 68 if len(data) == 4: 69 s = data[3] 70 i = s.find('+') 71 if i > 0: 72 data[3:] = [s[:i], s[i + 1:]] 73 else: 74 data.append('') 75 if len(data) < 5: 76 return 77 data = data[:5] 78 dd, mm, yy, tm, tz = data 79 mm = mm.lower() 80 if mm not in _monthnames: 81 dd, mm = mm, dd.lower() 82 if mm not in _monthnames: 83 return 84 mm = _monthnames.index(mm) + 1 85 if mm > 12: 86 mm -= 12 87 if dd[-1] == ',': 88 dd = dd[:-1] 89 i = yy.find(':') 90 if i > 0: 91 yy, tm = tm, yy 92 if yy[-1] == ',': 93 yy = yy[:-1] 94 if not yy[0].isdigit(): 95 yy, tz = tz, yy 96 if tm[-1] == ',': 97 tm = tm[:-1] 98 tm = tm.split(':') 99 if len(tm) == 2: 100 thh, tmm = tm 101 tss = '0' 102 elif len(tm) == 3: 103 thh, tmm, tss = tm 104 else: 105 return 106 try: 107 yy = int(yy) 108 dd = int(dd) 109 thh = int(thh) 110 tmm = int(tmm) 111 tss = int(tss) 112 except ValueError: 113 return 114 115 if yy < 100: 116 if yy > 68: 117 yy += 1900 118 else: 119 yy += 2000 120 tzoffset = None 121 tz = tz.upper() 122 if tz in _timezones: 123 tzoffset = _timezones[tz] 124 else: 125 try: 126 tzoffset = int(tz) 127 except ValueError: 128 pass 129 130 if tzoffset: 131 if tzoffset < 0: 132 tzsign = -1 133 tzoffset = -tzoffset 134 else: 135 tzsign = 1 136 tzoffset = tzsign * (tzoffset // 100 * 3600 + tzoffset % 100 * 60) 137 return (yy, 138 mm, 139 dd, 140 thh, 141 tmm, 142 tss, 143 0, 144 1, 145 -1, 146 tzoffset) 147 148 149 def parsedate(data): 150 t = parsedate_tz(data) 151 if isinstance(t, tuple): 152 return t[:9] 153 else: 154 return t 155 156 157 def mktime_tz(data): 158 if data[9] is None: 159 return time.mktime(data[:8] + (-1,)) 160 else: 161 t = time.mktime(data[:8] + (0,)) 162 return t - data[9] - time.timezone 163 164 165 def quote(str): 166 return str.replace('\\', '\\\\').replace('"', '\\"') 167 168 169 class AddrlistClass(): 170 171 def __init__(self, field): 172 self.specials = '()<>@,:;."[]' 173 self.pos = 0 174 self.LWS = ' \t' 175 self.CR = '\r\n' 176 self.FWS = self.LWS + self.CR 177 self.atomends = self.specials + self.LWS + self.CR 178 self.phraseends = self.atomends.replace('.', '') 179 self.field = field 180 self.commentlist = [] 181 182 def gotonext(self): 183 while self.pos < len(self.field): 184 if self.field[self.pos] in self.LWS + '\n\r': 185 self.pos += 1 186 elif self.field[self.pos] == '(': 187 self.commentlist.append(self.getcomment()) 188 else: 189 break 190 191 def getaddrlist(self): 192 result = [] 193 while self.pos < len(self.field): 194 ad = self.getaddress() 195 if ad: 196 result += ad 197 else: 198 result.append(('', '')) 199 200 return result 201 202 def getaddress(self): 203 self.commentlist = [] 204 self.gotonext() 205 oldpos = self.pos 206 oldcl = self.commentlist 207 plist = self.getphraselist() 208 self.gotonext() 209 returnlist = [] 210 if self.pos >= len(self.field): 211 if plist: 212 returnlist = [(SPACE.join(self.commentlist), plist[0])] 213 elif self.field[self.pos] in '.@': 214 self.pos = oldpos 215 self.commentlist = oldcl 216 addrspec = self.getaddrspec() 217 returnlist = [(SPACE.join(self.commentlist), addrspec)] 218 elif self.field[self.pos] == ':': 219 returnlist = [] 220 fieldlen = len(self.field) 221 self.pos += 1 222 while self.pos < len(self.field): 223 self.gotonext() 224 if self.pos < fieldlen and self.field[self.pos] == ';': 225 self.pos += 1 226 break 227 returnlist = returnlist + self.getaddress() 228 229 elif self.field[self.pos] == '<': 230 routeaddr = self.getrouteaddr() 231 if self.commentlist: 232 returnlist = [(SPACE.join(plist) + ' (' + ' '.join(self.commentlist) + ')', routeaddr)] 233 else: 234 returnlist = [(SPACE.join(plist), routeaddr)] 235 elif plist: 236 returnlist = [(SPACE.join(self.commentlist), plist[0])] 237 elif self.field[self.pos] in self.specials: 238 self.pos += 1 239 self.gotonext() 240 if self.pos < len(self.field) and self.field[self.pos] == ',': 241 self.pos += 1 242 return returnlist 243 244 def getrouteaddr(self): 245 if self.field[self.pos] != '<': 246 return 247 expectroute = False 248 self.pos += 1 249 self.gotonext() 250 adlist = '' 251 while self.pos < len(self.field): 252 if expectroute: 253 self.getdomain() 254 expectroute = False 255 elif self.field[self.pos] == '>': 256 self.pos += 1 257 break 258 elif self.field[self.pos] == '@': 259 self.pos += 1 260 expectroute = True 261 elif self.field[self.pos] == ':': 262 self.pos += 1 263 else: 264 adlist = self.getaddrspec() 265 self.pos += 1 266 break 267 self.gotonext() 268 269 return adlist 270 271 def getaddrspec(self): 272 aslist = [] 273 self.gotonext() 274 while self.pos < len(self.field): 275 if self.field[self.pos] == '.': 276 aslist.append('.') 277 self.pos += 1 278 elif self.field[self.pos] == '"': 279 aslist.append('"%s"' % quote(self.getquote())) 280 elif self.field[self.pos] in self.atomends: 281 break 282 else: 283 aslist.append(self.getatom()) 284 self.gotonext() 285 286 if self.pos >= len(self.field) or self.field[self.pos] != '@': 287 return EMPTYSTRING.join(aslist) 288 aslist.append('@') 289 self.pos += 1 290 self.gotonext() 291 return EMPTYSTRING.join(aslist) + self.getdomain() 292 293 def getdomain(self): 294 sdlist = [] 295 while self.pos < len(self.field): 296 if self.field[self.pos] in self.LWS: 297 self.pos += 1 298 elif self.field[self.pos] == '(': 299 self.commentlist.append(self.getcomment()) 300 elif self.field[self.pos] == '[': 301 sdlist.append(self.getdomainliteral()) 302 elif self.field[self.pos] == '.': 303 self.pos += 1 304 sdlist.append('.') 305 elif self.field[self.pos] in self.atomends: 306 break 307 else: 308 sdlist.append(self.getatom()) 309 310 return EMPTYSTRING.join(sdlist) 311 312 def getdelimited(self, beginchar, endchars, allowcomments = True): 313 if self.field[self.pos] != beginchar: 314 return '' 315 slist = [''] 316 quote = False 317 self.pos += 1 318 while self.pos < len(self.field): 319 if quote: 320 slist.append(self.field[self.pos]) 321 quote = False 322 elif self.field[self.pos] in endchars: 323 self.pos += 1 324 break 325 elif allowcomments and self.field[self.pos] == '(': 326 slist.append(self.getcomment()) 327 continue 328 elif self.field[self.pos] == '\\': 329 quote = True 330 else: 331 slist.append(self.field[self.pos]) 332 self.pos += 1 333 334 return EMPTYSTRING.join(slist) 335 336 def getquote(self): 337 return self.getdelimited('"', '"\r', False) 338 339 def getcomment(self): 340 return self.getdelimited('(', ')\r', True) 341 342 def getdomainliteral(self): 343 return '[%s]' % self.getdelimited('[', ']\r', False) 344 345 def getatom(self, atomends = None): 346 atomlist = [''] 347 if atomends is None: 348 atomends = self.atomends 349 while self.pos < len(self.field): 350 if self.field[self.pos] in atomends: 351 break 352 else: 353 atomlist.append(self.field[self.pos]) 354 self.pos += 1 355 356 return EMPTYSTRING.join(atomlist) 357 358 def getphraselist(self): 359 plist = [] 360 while self.pos < len(self.field): 361 if self.field[self.pos] in self.FWS: 362 self.pos += 1 363 elif self.field[self.pos] == '"': 364 plist.append(self.getquote()) 365 elif self.field[self.pos] == '(': 366 self.commentlist.append(self.getcomment()) 367 elif self.field[self.pos] in self.phraseends: 368 break 369 else: 370 plist.append(self.getatom(self.phraseends)) 371 372 return plist 373 374 375 class AddressList(AddrlistClass): 376 377 def __init__(self, field): 378 AddrlistClass.__init__(self, field) 379 if field: 380 self.addresslist = self.getaddrlist() 381 else: 382 self.addresslist = [] 383 384 def __len__(self): 385 return len(self.addresslist) 386 387 def __add__(self, other): 388 newaddr = AddressList(None) 389 newaddr.addresslist = self.addresslist[:] 390 for x in other.addresslist: 391 if x not in self.addresslist: 392 newaddr.addresslist.append(x) 393 394 return newaddr 395 396 def __iadd__(self, other): 397 for x in other.addresslist: 398 if x not in self.addresslist: 399 self.addresslist.append(x) 400 401 return self 402 403 def __sub__(self, other): 404 newaddr = AddressList(None) 405 for x in self.addresslist: 406 if x not in other.addresslist: 407 newaddr.addresslist.append(x) 408 409 return newaddr 410 411 def __isub__(self, other): 412 for x in other.addresslist: 413 if x in self.addresslist: 414 self.addresslist.remove(x) 415 416 return self 417 418 def __getitem__(self, index): 419 return self.addresslist[index]