| |   |
| 26 | 26 | import Text.ParserCombinators.Parsec.Rfc2234 |
| 27 | 27 | hiding ( quoted_pair, quoted_string ) |
| 28 | 28 | |
| data NameAddr = NameAddr { nameAddr_name :: Maybe String |
| , nameAddr_addr :: String } |
| deriving (Show,Eq) |
|
| 29 | 33 | -- * Useful parser combinators |
| 30 | 34 | |
| 31 | 35 | -- |@unfold@ @=@ @between (optional cfws) (optional cfws)@ |
| … | … | |
| 402 | 402 | -- |Parse a single 'mailbox' or an address 'group' and return the |
| 403 | 403 | -- address(es). |
| 404 | 404 | |
| address :: CharParser a [String] |
| address :: CharParser a [NameAddr] |
| 406 | 406 | address = try (do { r <- mailbox; return [r] }) <|> group |
| 407 | 407 | <?> "address" |
| 408 | 408 | |
| 409 | 409 | -- |Parse a 'name_addr' or an 'addr_spec' and return the |
| 410 | 410 | -- address. |
| 411 | 411 | |
| mailbox :: CharParser a String |
| mailbox = try name_addr <|> addr_spec |
| mailbox :: CharParser a NameAddr |
| mailbox = try name_addr <|> (addr_spec >>= return . NameAddr Nothing) |
| 414 | 414 | <?> "mailbox" |
| 415 | 415 | |
| 416 | 416 | -- |Parse an 'angle_addr', optionally prefaced with a 'display_name', |
| 417 | 417 | -- and return the address. |
| 418 | 418 | |
| name_addr :: CharParser a String |
| name_addr = do optional display_name |
| angle_addr |
| name_addr :: CharParser a NameAddr |
| name_addr = do name <- optionMaybe display_name |
| addr <- angle_addr |
| return (NameAddr name addr) |
| 422 | 423 | <?> "name address" |
| 423 | 424 | |
| 424 | 425 | -- |Parse an 'angle_addr' or an 'obs_angle_addr' and return the address. |
| … | … | |
| 444 | 444 | -- |
| 445 | 445 | -- > Right ["user1@example.org","user2@example.org"] |
| 446 | 446 | |
| group :: CharParser a [String] |
| group :: CharParser a [NameAddr] |
| 448 | 448 | group = do display_name |
| 449 | 449 | char ':' |
| 450 | 450 | r <- option [] mailbox_list |
| … | … | |
| 454 | 454 | |
| 455 | 455 | -- |Parse and return a 'phrase'. |
| 456 | 456 | |
| display_name :: CharParser a [String] |
| display_name = phrase <?> "display name" |
| display_name :: CharParser a String |
| display_name = phrase >>= return . concat . intersperse " " |
| <?> "display name" |
| 459 | 460 | |
| 460 | 461 | -- |Parse a list of 'mailbox' addresses, every two addresses being |
| 461 | 462 | -- separated by a comma, and return the list of found address(es). |
| 462 | 463 | |
| mailbox_list :: CharParser a [String] |
| mailbox_list :: CharParser a [NameAddr] |
| 464 | 465 | mailbox_list = sepBy mailbox (char ',') <?> "mailbox list" |
| 465 | 466 | |
| 466 | 467 | -- |Parse a list of 'address' addresses, every two addresses being |
| 467 | 468 | -- separated by a comma, and return the list of found address(es). |
| 468 | 469 | |
| address_list :: CharParser a [String] |
| address_list :: CharParser a [NameAddr] |
| 470 | 471 | address_list = do { r <-sepBy address (char ','); return (concat r) } |
| 471 | 472 | <?> "address list" |
| 472 | 473 | |
| … | … | |
| 580 | 580 | -- of the corresponding parser. |
| 581 | 581 | |
| 582 | 582 | data Field = OptionalField String String |
| | From [String] |
| | Sender String |
| | From [NameAddr] |
| | Sender NameAddr |
| 585 | 585 | | ReturnPath String |
| | ReplyTo [String] |
| | To [String] |
| | Cc [String] |
| | Bcc [String] |
| | ReplyTo [NameAddr] |
| | To [NameAddr] |
| | Cc [NameAddr] |
| | Bcc [NameAddr] |
| 590 | 590 | | MessageID String |
| 591 | 591 | | InReplyTo [String] |
| 592 | 592 | | References [String] |
| … | … | |
| 595 | 595 | | Keywords [[String]] |
| 596 | 596 | | Date CalendarTime |
| 597 | 597 | | ResentDate CalendarTime |
| | ResentFrom [String] |
| | ResentSender String |
| | ResentTo [String] |
| | ResentCc [String] |
| | ResentBcc [String] |
| | ResentFrom [NameAddr] |
| | ResentSender NameAddr |
| | ResentTo [NameAddr] |
| | ResentCc [NameAddr] |
| | ResentBcc [NameAddr] |
| 603 | 603 | | ResentMessageID String |
| | ResentReplyTo [String] |
| | ResentReplyTo [NameAddr] |
| 605 | 605 | | Received ([(String,String)], CalendarTime) |
| 606 | 606 | | ObsReceived [(String,String)] |
| 607 | 607 | deriving (Show) |
| … | … | |
| 660 | 660 | -- |Parse a \"@From:@\" header line and return the 'mailbox_list' |
| 661 | 661 | -- address(es) contained in it. |
| 662 | 662 | |
| from :: CharParser a [String] |
| from :: CharParser a [NameAddr] |
| 664 | 664 | from = header "From" mailbox_list |
| 665 | 665 | |
| 666 | 666 | -- |Parse a \"@Sender:@\" header line and return the 'mailbox' address |
| 667 | 667 | -- contained in it. |
| 668 | 668 | |
| sender :: CharParser a String |
| sender :: CharParser a NameAddr |
| 670 | 670 | sender = header "Sender" mailbox |
| 671 | 671 | |
| 672 | 672 | -- |Parse a \"@Reply-To:@\" header line and return the 'address_list' |
| 673 | 673 | -- address(es) contained in it. |
| 674 | 674 | |
| reply_to :: CharParser a [String] |
| reply_to :: CharParser a [NameAddr] |
| 676 | 676 | reply_to = header "Reply-To" address_list |
| 677 | 677 | |
| 678 | 678 | |
| … | … | |
| 681 | 681 | -- |Parse a \"@To:@\" header line and return the 'address_list' |
| 682 | 682 | -- address(es) contained in it. |
| 683 | 683 | |
| to :: CharParser a [String] |
| to :: CharParser a [NameAddr] |
| 685 | 685 | to = header "To" address_list |
| 686 | 686 | |
| 687 | 687 | -- |Parse a \"@Cc:@\" header line and return the 'address_list' |
| 688 | 688 | -- address(es) contained in it. |
| 689 | 689 | |
| cc :: CharParser a [String] |
| cc :: CharParser a [NameAddr] |
| 691 | 691 | cc = header "Cc" address_list |
| 692 | 692 | |
| 693 | 693 | -- |Parse a \"@Bcc:@\" header line and return the 'address_list' |
| 694 | 694 | -- address(es) contained in it. |
| 695 | 695 | |
| bcc :: CharParser a [String] |
| bcc :: CharParser a [NameAddr] |
| 697 | 697 | bcc = header "Bcc" (try address_list <|> do { optional cfws; return [] }) |
| 698 | 698 | |
| 699 | 699 | -- ** Identification fields (section 3.6.4) |
| … | … | |
| 804 | 804 | -- |Parse a \"@Resent-From:@\" header line and return the 'mailbox_list' |
| 805 | 805 | -- address(es) contained in it. |
| 806 | 806 | |
| resent_from :: CharParser a [String] |
| resent_from :: CharParser a [NameAddr] |
| 808 | 808 | resent_from = header "Resent-From" mailbox_list |
| 809 | 809 | |
| 810 | 810 | |
| 811 | 811 | -- |Parse a \"@Resent-Sender:@\" header line and return the 'mailbox_list' |
| 812 | 812 | -- address(es) contained in it. |
| 813 | 813 | |
| resent_sender :: CharParser a String |
| resent_sender :: CharParser a NameAddr |
| 815 | 815 | resent_sender = header "Resent-Sender" mailbox |
| 816 | 816 | |
| 817 | 817 | |
| 818 | 818 | -- |Parse a \"@Resent-To:@\" header line and return the 'mailbox' |
| 819 | 819 | -- address contained in it. |
| 820 | 820 | |
| resent_to :: CharParser a [String] |
| resent_to :: CharParser a [NameAddr] |
| 822 | 822 | resent_to = header "Resent-To" address_list |
| 823 | 823 | |
| 824 | 824 | -- |Parse a \"@Resent-Cc:@\" header line and return the 'address_list' |
| 825 | 825 | -- address(es) contained in it. |
| 826 | 826 | |
| resent_cc :: CharParser a [String] |
| resent_cc :: CharParser a [NameAddr] |
| 828 | 828 | resent_cc = header "Resent-Cc" address_list |
| 829 | 829 | |
| 830 | 830 | -- |Parse a \"@Resent-Bcc:@\" header line and return the 'address_list' |
| 831 | 831 | -- address(es) contained in it. (This list may be empty.) |
| 832 | 832 | |
| resent_bcc :: CharParser a [String] |
| resent_bcc :: CharParser a [NameAddr] |
| 834 | 834 | resent_bcc = header "Resent-Bcc" ( try address_list |
| 835 | 835 | <|> do optional cfws |
| 836 | 836 | return [] |
| … | … | |
| 1160 | 1160 | -- |
| 1161 | 1161 | -- Strange, isn't it? |
| 1162 | 1162 | |
| obs_mbox_list :: CharParser a [String] |
| obs_mbox_list = do r1 <- many1 (try (do r <- option [] mailbox |
| obs_mbox_list :: CharParser a [NameAddr] |
| obs_mbox_list = do r1 <- many1 (try (do r <- optionMaybe mailbox |
| 1165 | 1165 | unfold $ char ',' |
| 1166 | 1166 | return r)) |
| r2 <- option [] mailbox |
| return (filter (/=[]) (r1 ++ [r2])) |
| r2 <- optionMaybe mailbox |
| return [x | Just x <- r1 ++ [r2]] |
| 1169 | 1169 | <?> "obsolete syntax for a list of mailboxes" |
| 1170 | 1170 | |
| 1171 | 1171 | -- |This parser is identical to 'obs_mbox_list' but parses a list of |
| … | … | |
| 1174 | 1174 | -- parser will return a simple list of addresses; the grouping |
| 1175 | 1175 | -- information is lost. |
| 1176 | 1176 | |
| obs_addr_list :: CharParser a [String] |
| obs_addr_list = do r1 <- many1 (try (do r <- option [] address |
| obs_addr_list :: CharParser a [NameAddr] |
| obs_addr_list = do r1 <- many1 (try (do r <- optionMaybe address |
| 1179 | 1179 | optional cfws |
| 1180 | 1180 | char ',' |
| 1181 | 1181 | optional cfws |
| return (concat r))) |
| r2 <- option [] address |
| return (filter (/=[]) (r1 ++ r2)) |
| return r)) |
| r2 <- optionMaybe address |
| return (concat [x | Just x <- r1 ++ [r2]]) |
| 1185 | 1185 | <?> "obsolete syntax for a list of addresses" |
| 1186 | 1186 | |
| 1187 | 1187 | |
| … | … | |
| 1230 | 1230 | -- |Parse a 'from' header line but allow for the obsolete |
| 1231 | 1231 | -- folding syntax. |
| 1232 | 1232 | |
| obs_from :: CharParser a [String] |
| obs_from :: CharParser a [NameAddr] |
| 1234 | 1234 | obs_from = obs_header "From" mailbox_list |
| 1235 | 1235 | |
| 1236 | 1236 | -- |Parse a 'sender' header line but allow for the obsolete |
| 1237 | 1237 | -- folding syntax. |
| 1238 | 1238 | |
| obs_sender :: CharParser a String |
| obs_sender :: CharParser a NameAddr |
| 1240 | 1240 | obs_sender = obs_header "Sender" mailbox |
| 1241 | 1241 | |
| 1242 | 1242 | -- |Parse a 'reply_to' header line but allow for the obsolete |
| 1243 | 1243 | -- folding syntax. |
| 1244 | 1244 | |
| obs_reply_to :: CharParser a [String] |
| obs_reply_to :: CharParser a [NameAddr] |
| 1246 | 1246 | obs_reply_to = obs_header "Reply-To" mailbox_list |
| 1247 | 1247 | |
| 1248 | 1248 | |
| … | … | |
| 1251 | 1251 | -- |Parse a 'to' header line but allow for the obsolete |
| 1252 | 1252 | -- folding syntax. |
| 1253 | 1253 | |
| obs_to :: CharParser a [String] |
| obs_to :: CharParser a [NameAddr] |
| 1255 | 1255 | obs_to = obs_header "To" address_list |
| 1256 | 1256 | |
| 1257 | 1257 | -- |Parse a 'cc' header line but allow for the obsolete |
| 1258 | 1258 | -- folding syntax. |
| 1259 | 1259 | |
| obs_cc :: CharParser a [String] |
| obs_cc :: CharParser a [NameAddr] |
| 1261 | 1261 | obs_cc = obs_header "Cc" address_list |
| 1262 | 1262 | |
| 1263 | 1263 | -- |Parse a 'bcc' header line but allow for the obsolete |
| 1264 | 1264 | -- folding syntax. |
| 1265 | 1265 | |
| obs_bcc :: CharParser a [String] |
| obs_bcc :: CharParser a [NameAddr] |
| 1267 | 1267 | obs_bcc = header "Bcc" ( try address_list |
| 1268 | 1268 | <|> do { optional cfws; return [] } |
| 1269 | 1269 | ) |
| … | … | |
| 1335 | 1335 | -- |Parse a 'resent_from' header line but allow for the obsolete |
| 1336 | 1336 | -- folding syntax. |
| 1337 | 1337 | |
| obs_resent_from :: CharParser a [String] |
| obs_resent_from :: CharParser a [NameAddr] |
| 1339 | 1339 | obs_resent_from = obs_header "Resent-From" mailbox_list |
| 1340 | 1340 | |
| 1341 | 1341 | -- |Parse a 'resent_sender' header line but allow for the obsolete |
| 1342 | 1342 | -- folding syntax. |
| 1343 | 1343 | |
| obs_resent_send :: CharParser a String |
| obs_resent_send :: CharParser a NameAddr |
| 1345 | 1345 | obs_resent_send = obs_header "Resent-Sender" mailbox |
| 1346 | 1346 | |
| 1347 | 1347 | -- |Parse a 'resent_date' header line but allow for the obsolete |
| … | … | |
| 1353 | 1353 | -- |Parse a 'resent_to' header line but allow for the obsolete |
| 1354 | 1354 | -- folding syntax. |
| 1355 | 1355 | |
| obs_resent_to :: CharParser a [String] |
| obs_resent_to :: CharParser a [NameAddr] |
| 1357 | 1357 | obs_resent_to = obs_header "Resent-To" mailbox_list |
| 1358 | 1358 | |
| 1359 | 1359 | -- |Parse a 'resent_cc' header line but allow for the obsolete |
| 1360 | 1360 | -- folding syntax. |
| 1361 | 1361 | |
| obs_resent_cc :: CharParser a [String] |
| obs_resent_cc :: CharParser a [NameAddr] |
| 1363 | 1363 | obs_resent_cc = obs_header "Resent-Cc" mailbox_list |
| 1364 | 1364 | |
| 1365 | 1365 | -- |Parse a 'resent_bcc' header line but allow for the obsolete |
| 1366 | 1366 | -- folding syntax. |
| 1367 | 1367 | |
| obs_resent_bcc :: CharParser a [String] |
| obs_resent_bcc :: CharParser a [NameAddr] |
| 1369 | 1369 | obs_resent_bcc = obs_header "Bcc" ( try address_list |
| 1370 | 1370 | <|> do { optional cfws; return [] } |
| 1371 | 1371 | ) |
| … | … | |
| 1379 | 1379 | -- |Parse a @Resent-Reply-To@ header line but allow for the |
| 1380 | 1380 | -- obsolete folding syntax. |
| 1381 | 1381 | |
| obs_resent_reply :: CharParser a [String] |
| obs_resent_reply :: CharParser a [NameAddr] |
| 1383 | 1383 | obs_resent_reply = obs_header "Resent-Reply-To" address_list |
| 1384 | 1384 | |
| 1385 | 1385 | |