1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import re
20
21 import logging
22 try:
23 from logging import NullHandler
24 except ImportError:
26 - def emit(self, record):
28
29
30 __all__ = [
31 'DuplicateTag',
32 'get_default_logger',
33 'InvalidTagSpec',
34 'InvalidTagValueList',
35 'parse_tag_value',
36 'get_linesep',
37 ]
38
39
42
43
46
47
50
51
53 """Parse a DKIM Tag=Value list.
54
55 Interprets the syntax specified by RFC6376 section 3.2.
56 Assumes that folding whitespace is already unfolded.
57
58 @param tag_list: A bytes string containing a DKIM Tag=Value list.
59 """
60 tags = {}
61 tag_specs = tag_list.strip().split(b';')
62
63 if not tag_specs[-1]:
64 tag_specs.pop()
65 for tag_spec in tag_specs:
66 try:
67 key, value = [x.strip() for x in tag_spec.split(b'=', 1)]
68 except ValueError:
69 raise InvalidTagSpec(tag_spec)
70 if re.match(br'^[a-zA-Z](\w)*', key) is None:
71 raise InvalidTagSpec(tag_spec)
72 if key in tags:
73 raise DuplicateTag(key)
74 tags[key] = value
75 return tags
76
77
79 """Get the default dkimpy logger."""
80 logger = logging.getLogger('dkimpy')
81 if not logger.handlers:
82 logger.addHandler(NullHandler())
83 return logger
84
86 if msg[-2:] != b'\r\n' and msg[-1:] == b'\n':
87 return b'\n'
88 return b'\r\n'
89