pec_ruby 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env.example +10 -0
- data/.rspec_status +118 -99
- data/CHANGELOG.md +41 -2
- data/Gemfile.lock +1 -1
- data/README.md +89 -0
- data/lib/pec_ruby/attachment.rb +15 -0
- data/lib/pec_ruby/cli.rb +14 -3
- data/lib/pec_ruby/message.rb +64 -22
- data/lib/pec_ruby/version.rb +1 -1
- metadata +5 -4
- data/pec_ruby.gemspec +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75564798d9edfab567f803aaf9ee7b9068a3e7faef4b001abc715821bb2fbfb2
|
4
|
+
data.tar.gz: 79b0e130900ac009a359aca4cbe3c6be23619cacc272583d13050dd06202b5aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69f7cee3c6b534ead7f189c7522f97803a30105548b15584fc2021a6644260362b216b94493dd94498ea36e87f42b534188cb962dcfc3d08bc02266ad79229b5
|
7
|
+
data.tar.gz: d5ae1cbb18cc4623bb4156db1c82b31819738d3934663dc4fc8a13eb4e513c44c511caad39dc76129641e108a411a25c04c8e305a0881e2e3fab1528bf529491
|
data/.env.example
ADDED
data/.rspec_status
CHANGED
@@ -1,99 +1,118 @@
|
|
1
|
-
example_id
|
2
|
-
|
3
|
-
./spec/pec_ruby/attachment_spec.rb[1:1:1]
|
4
|
-
./spec/pec_ruby/attachment_spec.rb[1:2:1:1]
|
5
|
-
./spec/pec_ruby/attachment_spec.rb[1:2:2:1]
|
6
|
-
./spec/pec_ruby/attachment_spec.rb[1:3:1:1]
|
7
|
-
./spec/pec_ruby/attachment_spec.rb[1:3:2:1]
|
8
|
-
./spec/pec_ruby/attachment_spec.rb[1:4:1]
|
9
|
-
./spec/pec_ruby/attachment_spec.rb[1:5:1]
|
10
|
-
./spec/pec_ruby/attachment_spec.rb[1:6:1]
|
11
|
-
./spec/pec_ruby/attachment_spec.rb[1:7:1]
|
12
|
-
./spec/pec_ruby/attachment_spec.rb[1:8:1]
|
13
|
-
./spec/pec_ruby/attachment_spec.rb[1:8:2]
|
14
|
-
./spec/pec_ruby/attachment_spec.rb[1:9:1]
|
15
|
-
./spec/pec_ruby/attachment_spec.rb[1:10:1]
|
16
|
-
./spec/pec_ruby/attachment_spec.rb[1:11:1]
|
17
|
-
./spec/pec_ruby/attachment_spec.rb[1:12:1:1]
|
18
|
-
./spec/pec_ruby/attachment_spec.rb[1:12:2:1]
|
19
|
-
./spec/pec_ruby/attachment_spec.rb[1:12:3:1]
|
20
|
-
./spec/pec_ruby/attachment_spec.rb[1:13:1:1]
|
21
|
-
./spec/pec_ruby/attachment_spec.rb[1:13:2:1]
|
22
|
-
./spec/pec_ruby/attachment_spec.rb[1:13:3:1]
|
23
|
-
./spec/pec_ruby/attachment_spec.rb[2:1:1]
|
24
|
-
./spec/pec_ruby/attachment_spec.rb[2:2:1]
|
25
|
-
./spec/pec_ruby/attachment_spec.rb[2:3:1]
|
26
|
-
./spec/pec_ruby/attachment_spec.rb[2:4:1]
|
27
|
-
./spec/pec_ruby/attachment_spec.rb[2:5:1]
|
28
|
-
./spec/pec_ruby/attachment_spec.rb[2:6:1:1]
|
29
|
-
./spec/pec_ruby/attachment_spec.rb[2:6:2:1]
|
30
|
-
./spec/pec_ruby/attachment_spec.rb[2:7:1]
|
31
|
-
./spec/pec_ruby/attachment_spec.rb[2:8:1:1]
|
32
|
-
./spec/pec_ruby/attachment_spec.rb[2:8:2:1]
|
33
|
-
./spec/pec_ruby/client_spec.rb[1:1:1]
|
34
|
-
./spec/pec_ruby/client_spec.rb[1:1:2]
|
35
|
-
./spec/pec_ruby/client_spec.rb[1:1:3]
|
36
|
-
./spec/pec_ruby/client_spec.rb[1:2:1:1]
|
37
|
-
./spec/pec_ruby/client_spec.rb[1:2:2:1]
|
38
|
-
./spec/pec_ruby/client_spec.rb[1:2:3:1]
|
39
|
-
./spec/pec_ruby/client_spec.rb[1:3:1]
|
40
|
-
./spec/pec_ruby/client_spec.rb[1:3:2]
|
41
|
-
./spec/pec_ruby/client_spec.rb[1:3:3]
|
42
|
-
./spec/pec_ruby/client_spec.rb[1:3:4]
|
43
|
-
./spec/pec_ruby/client_spec.rb[1:3:5:1]
|
44
|
-
./spec/pec_ruby/client_spec.rb[1:3:6:1]
|
45
|
-
./spec/pec_ruby/client_spec.rb[1:4:1:1]
|
46
|
-
./spec/pec_ruby/client_spec.rb[1:4:1:2]
|
47
|
-
./spec/pec_ruby/client_spec.rb[1:4:2:1]
|
48
|
-
./spec/pec_ruby/client_spec.rb[1:4:3:1]
|
49
|
-
./spec/pec_ruby/client_spec.rb[1:5:1:1]
|
50
|
-
./spec/pec_ruby/client_spec.rb[1:5:2:1]
|
51
|
-
./spec/pec_ruby/client_spec.rb[1:5:2:2]
|
52
|
-
./spec/pec_ruby/client_spec.rb[1:5:2:3]
|
53
|
-
./spec/pec_ruby/client_spec.rb[1:5:2:4]
|
54
|
-
./spec/pec_ruby/client_spec.rb[1:6:1:1]
|
55
|
-
./spec/pec_ruby/client_spec.rb[1:6:2:1]
|
56
|
-
./spec/pec_ruby/client_spec.rb[1:6:2:2]
|
57
|
-
./spec/pec_ruby/client_spec.rb[1:6:3:1]
|
58
|
-
./spec/pec_ruby/
|
59
|
-
./spec/pec_ruby/
|
60
|
-
./spec/pec_ruby/
|
61
|
-
./spec/pec_ruby/
|
62
|
-
./spec/pec_ruby/
|
63
|
-
./spec/pec_ruby/
|
64
|
-
./spec/pec_ruby/
|
65
|
-
./spec/pec_ruby/
|
66
|
-
./spec/pec_ruby/
|
67
|
-
./spec/pec_ruby/message_spec.rb[1:
|
68
|
-
./spec/pec_ruby/message_spec.rb[1:
|
69
|
-
./spec/pec_ruby/message_spec.rb[1:
|
70
|
-
./spec/pec_ruby/message_spec.rb[1:
|
71
|
-
./spec/pec_ruby/message_spec.rb[1:
|
72
|
-
./spec/pec_ruby/message_spec.rb[1:
|
73
|
-
./spec/pec_ruby/message_spec.rb[1:
|
74
|
-
./spec/pec_ruby/message_spec.rb[1:
|
75
|
-
./spec/pec_ruby/message_spec.rb[1:
|
76
|
-
./spec/pec_ruby/message_spec.rb[1:
|
77
|
-
./spec/pec_ruby/message_spec.rb[1:
|
78
|
-
./spec/pec_ruby/message_spec.rb[1:
|
79
|
-
./spec/pec_ruby/message_spec.rb[1:
|
80
|
-
./spec/pec_ruby/message_spec.rb[1:
|
81
|
-
./spec/pec_ruby/message_spec.rb[1:
|
82
|
-
./spec/pec_ruby/message_spec.rb[1:
|
83
|
-
./spec/pec_ruby/message_spec.rb[1:
|
84
|
-
./spec/pec_ruby/message_spec.rb[1:
|
85
|
-
./spec/pec_ruby/message_spec.rb[1:
|
86
|
-
./spec/pec_ruby/message_spec.rb[1:
|
87
|
-
./spec/pec_ruby/message_spec.rb[1:
|
88
|
-
./spec/pec_ruby/message_spec.rb[1:
|
89
|
-
./spec/pec_ruby/message_spec.rb[1:
|
90
|
-
./spec/pec_ruby/message_spec.rb[1:
|
91
|
-
./spec/pec_ruby/message_spec.rb[1:
|
92
|
-
./spec/pec_ruby/message_spec.rb[1:
|
93
|
-
./spec/pec_ruby/message_spec.rb[1:
|
94
|
-
./spec/
|
95
|
-
./spec/
|
96
|
-
./spec/
|
97
|
-
./spec/
|
98
|
-
./spec/
|
99
|
-
./spec/
|
1
|
+
example_id | status | run_time |
|
2
|
+
-------------------------------------------------- | ------ | --------------- |
|
3
|
+
./spec/pec_ruby/attachment_spec.rb[1:1:1] | passed | 0.00042 seconds |
|
4
|
+
./spec/pec_ruby/attachment_spec.rb[1:2:1:1] | passed | 0.00414 seconds |
|
5
|
+
./spec/pec_ruby/attachment_spec.rb[1:2:2:1] | passed | 0.0001 seconds |
|
6
|
+
./spec/pec_ruby/attachment_spec.rb[1:3:1:1] | passed | 0.00008 seconds |
|
7
|
+
./spec/pec_ruby/attachment_spec.rb[1:3:2:1] | passed | 0.00007 seconds |
|
8
|
+
./spec/pec_ruby/attachment_spec.rb[1:4:1] | passed | 0.00007 seconds |
|
9
|
+
./spec/pec_ruby/attachment_spec.rb[1:5:1] | passed | 0.00007 seconds |
|
10
|
+
./spec/pec_ruby/attachment_spec.rb[1:6:1] | passed | 0.00007 seconds |
|
11
|
+
./spec/pec_ruby/attachment_spec.rb[1:7:1] | passed | 0.00028 seconds |
|
12
|
+
./spec/pec_ruby/attachment_spec.rb[1:8:1] | passed | 0.00041 seconds |
|
13
|
+
./spec/pec_ruby/attachment_spec.rb[1:8:2] | passed | 0.00031 seconds |
|
14
|
+
./spec/pec_ruby/attachment_spec.rb[1:9:1] | passed | 0.00062 seconds |
|
15
|
+
./spec/pec_ruby/attachment_spec.rb[1:10:1] | passed | 0.00046 seconds |
|
16
|
+
./spec/pec_ruby/attachment_spec.rb[1:11:1] | passed | 0.00013 seconds |
|
17
|
+
./spec/pec_ruby/attachment_spec.rb[1:12:1:1] | passed | 0.00192 seconds |
|
18
|
+
./spec/pec_ruby/attachment_spec.rb[1:12:2:1] | passed | 0.00014 seconds |
|
19
|
+
./spec/pec_ruby/attachment_spec.rb[1:12:3:1] | passed | 0.0001 seconds |
|
20
|
+
./spec/pec_ruby/attachment_spec.rb[1:13:1:1] | passed | 0.00088 seconds |
|
21
|
+
./spec/pec_ruby/attachment_spec.rb[1:13:2:1] | passed | 0.00019 seconds |
|
22
|
+
./spec/pec_ruby/attachment_spec.rb[1:13:3:1] | passed | 0.00074 seconds |
|
23
|
+
./spec/pec_ruby/attachment_spec.rb[2:1:1] | passed | 0.0002 seconds |
|
24
|
+
./spec/pec_ruby/attachment_spec.rb[2:2:1] | passed | 0.00007 seconds |
|
25
|
+
./spec/pec_ruby/attachment_spec.rb[2:3:1] | passed | 0.00007 seconds |
|
26
|
+
./spec/pec_ruby/attachment_spec.rb[2:4:1] | passed | 0.00007 seconds |
|
27
|
+
./spec/pec_ruby/attachment_spec.rb[2:5:1] | passed | 0.00007 seconds |
|
28
|
+
./spec/pec_ruby/attachment_spec.rb[2:6:1:1] | passed | 0.00007 seconds |
|
29
|
+
./spec/pec_ruby/attachment_spec.rb[2:6:2:1] | passed | 0.00015 seconds |
|
30
|
+
./spec/pec_ruby/attachment_spec.rb[2:7:1] | passed | 0.00019 seconds |
|
31
|
+
./spec/pec_ruby/attachment_spec.rb[2:8:1:1] | passed | 0.00008 seconds |
|
32
|
+
./spec/pec_ruby/attachment_spec.rb[2:8:2:1] | passed | 0.00007 seconds |
|
33
|
+
./spec/pec_ruby/client_spec.rb[1:1:1] | passed | 0.00004 seconds |
|
34
|
+
./spec/pec_ruby/client_spec.rb[1:1:2] | passed | 0.00003 seconds |
|
35
|
+
./spec/pec_ruby/client_spec.rb[1:1:3] | passed | 0.00003 seconds |
|
36
|
+
./spec/pec_ruby/client_spec.rb[1:2:1:1] | passed | 0.00003 seconds |
|
37
|
+
./spec/pec_ruby/client_spec.rb[1:2:2:1] | passed | 0.00008 seconds |
|
38
|
+
./spec/pec_ruby/client_spec.rb[1:2:3:1] | passed | 0.00007 seconds |
|
39
|
+
./spec/pec_ruby/client_spec.rb[1:3:1] | passed | 0.00036 seconds |
|
40
|
+
./spec/pec_ruby/client_spec.rb[1:3:2] | passed | 0.0002 seconds |
|
41
|
+
./spec/pec_ruby/client_spec.rb[1:3:3] | passed | 0.00018 seconds |
|
42
|
+
./spec/pec_ruby/client_spec.rb[1:3:4] | passed | 0.00015 seconds |
|
43
|
+
./spec/pec_ruby/client_spec.rb[1:3:5:1] | passed | 0.00019 seconds |
|
44
|
+
./spec/pec_ruby/client_spec.rb[1:3:6:1] | passed | 0.00017 seconds |
|
45
|
+
./spec/pec_ruby/client_spec.rb[1:4:1:1] | passed | 0.00014 seconds |
|
46
|
+
./spec/pec_ruby/client_spec.rb[1:4:1:2] | passed | 0.00022 seconds |
|
47
|
+
./spec/pec_ruby/client_spec.rb[1:4:2:1] | passed | 0.00004 seconds |
|
48
|
+
./spec/pec_ruby/client_spec.rb[1:4:3:1] | passed | 0.00014 seconds |
|
49
|
+
./spec/pec_ruby/client_spec.rb[1:5:1:1] | passed | 0.0001 seconds |
|
50
|
+
./spec/pec_ruby/client_spec.rb[1:5:2:1] | passed | 0.0002 seconds |
|
51
|
+
./spec/pec_ruby/client_spec.rb[1:5:2:2] | passed | 0.00032 seconds |
|
52
|
+
./spec/pec_ruby/client_spec.rb[1:5:2:3] | passed | 0.00021 seconds |
|
53
|
+
./spec/pec_ruby/client_spec.rb[1:5:2:4] | passed | 0.0002 seconds |
|
54
|
+
./spec/pec_ruby/client_spec.rb[1:6:1:1] | passed | 0.0001 seconds |
|
55
|
+
./spec/pec_ruby/client_spec.rb[1:6:2:1] | passed | 0.00029 seconds |
|
56
|
+
./spec/pec_ruby/client_spec.rb[1:6:2:2] | passed | 0.00018 seconds |
|
57
|
+
./spec/pec_ruby/client_spec.rb[1:6:3:1] | passed | 0.0001 seconds |
|
58
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:1:1] | failed | 0.00443 seconds |
|
59
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:1:2] | failed | 0.00093 seconds |
|
60
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:1:3] | failed | 0.00062 seconds |
|
61
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:2:1] | failed | 0.00061 seconds |
|
62
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:3:1] | failed | 0.0007 seconds |
|
63
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:3:2] | failed | 0.00061 seconds |
|
64
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:4:1] | failed | 0.00057 seconds |
|
65
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:4:2] | failed | 0.00056 seconds |
|
66
|
+
./spec/pec_ruby/message_refactoring_spec.rb[1:5:1] | failed | 0.00063 seconds |
|
67
|
+
./spec/pec_ruby/message_spec.rb[1:1:1] | passed | 0.00013 seconds |
|
68
|
+
./spec/pec_ruby/message_spec.rb[1:2:1:1] | passed | 0.00013 seconds |
|
69
|
+
./spec/pec_ruby/message_spec.rb[1:2:2:1] | passed | 0.00015 seconds |
|
70
|
+
./spec/pec_ruby/message_spec.rb[1:2:2:2:1] | passed | 0.00016 seconds |
|
71
|
+
./spec/pec_ruby/message_spec.rb[1:3:1:1] | passed | 0.00015 seconds |
|
72
|
+
./spec/pec_ruby/message_spec.rb[1:3:2:1] | passed | 0.00012 seconds |
|
73
|
+
./spec/pec_ruby/message_spec.rb[1:3:2:2:1] | passed | 0.00012 seconds |
|
74
|
+
./spec/pec_ruby/message_spec.rb[1:4:1:1] | passed | 0.00009 seconds |
|
75
|
+
./spec/pec_ruby/message_spec.rb[1:4:2:1] | passed | 0.00015 seconds |
|
76
|
+
./spec/pec_ruby/message_spec.rb[1:5:1:1] | passed | 0.00009 seconds |
|
77
|
+
./spec/pec_ruby/message_spec.rb[1:5:2:1] | passed | 0.0003 seconds |
|
78
|
+
./spec/pec_ruby/message_spec.rb[1:6:1:1] | passed | 0.00013 seconds |
|
79
|
+
./spec/pec_ruby/message_spec.rb[1:6:2:1] | passed | 0.0001 seconds |
|
80
|
+
./spec/pec_ruby/message_spec.rb[1:7:1:1] | passed | 0.0001 seconds |
|
81
|
+
./spec/pec_ruby/message_spec.rb[1:7:1:2] | passed | 0.00015 seconds |
|
82
|
+
./spec/pec_ruby/message_spec.rb[1:7:2:1] | passed | 0.00028 seconds |
|
83
|
+
./spec/pec_ruby/message_spec.rb[1:7:2:2] | passed | 0.00025 seconds |
|
84
|
+
./spec/pec_ruby/message_spec.rb[1:7:3:1] | passed | 0.00018 seconds |
|
85
|
+
./spec/pec_ruby/message_spec.rb[1:8:1:1] | passed | 0.00012 seconds |
|
86
|
+
./spec/pec_ruby/message_spec.rb[1:8:2:1] | passed | 0.00011 seconds |
|
87
|
+
./spec/pec_ruby/message_spec.rb[1:9:1:1] | passed | 0.00012 seconds |
|
88
|
+
./spec/pec_ruby/message_spec.rb[1:9:2:1] | passed | 0.00018 seconds |
|
89
|
+
./spec/pec_ruby/message_spec.rb[1:10:1:1] | passed | 0.0001 seconds |
|
90
|
+
./spec/pec_ruby/message_spec.rb[1:10:2:1] | passed | 0.00138 seconds |
|
91
|
+
./spec/pec_ruby/message_spec.rb[1:10:3:1] | passed | 0.0017 seconds |
|
92
|
+
./spec/pec_ruby/message_spec.rb[1:11:1:1] | passed | 0.00028 seconds |
|
93
|
+
./spec/pec_ruby/message_spec.rb[1:11:2:1] | passed | 0.00015 seconds |
|
94
|
+
./spec/pec_ruby/message_spec.rb[1:12:1:1] | passed | 0.00025 seconds |
|
95
|
+
./spec/pec_ruby/message_spec.rb[1:12:2:1] | passed | 0.00015 seconds |
|
96
|
+
./spec/pec_ruby/message_spec.rb[1:13:1] | passed | 0.00019 seconds |
|
97
|
+
./spec/pec_ruby/message_spec.rb[1:14:1] | passed | 0.00022 seconds |
|
98
|
+
./spec/pec_ruby/message_spec.rb[1:15:1:1] | passed | 0.00024 seconds |
|
99
|
+
./spec/pec_ruby/message_spec.rb[1:15:2:1] | passed | 0.00014 seconds |
|
100
|
+
./spec/pec_ruby/message_spec.rb[1:16:1] | passed | 0.00021 seconds |
|
101
|
+
./spec/pec_ruby/message_spec.rb[1:17:1] | passed | 0.00021 seconds |
|
102
|
+
./spec/pec_ruby/message_spec.rb[1:18:1] | passed | 0.00056 seconds |
|
103
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:1:1] | failed | 0.001 seconds |
|
104
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:1:2] | failed | 0.00055 seconds |
|
105
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:1:3] | failed | 0.00048 seconds |
|
106
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:1:4] | failed | 0.00054 seconds |
|
107
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:1:5] | failed | 0.00048 seconds |
|
108
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:1:6] | failed | 0.00049 seconds |
|
109
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:2:1] | failed | 0.00054 seconds |
|
110
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:2:2] | failed | 0.00053 seconds |
|
111
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:3:1] | failed | 0.00058 seconds |
|
112
|
+
./spec/pec_ruby/nested_postacert_spec.rb[1:3:2] | failed | 0.00059 seconds |
|
113
|
+
./spec/pec_ruby_spec.rb[1:1] | passed | 0.00003 seconds |
|
114
|
+
./spec/pec_ruby_spec.rb[1:2:1] | passed | 0.00004 seconds |
|
115
|
+
./spec/pec_ruby_spec.rb[1:2:2] | passed | 0.00003 seconds |
|
116
|
+
./spec/pec_ruby_spec.rb[1:2:3] | passed | 0.00002 seconds |
|
117
|
+
./spec/pec_ruby_spec.rb[1:2:4] | passed | 0.00002 seconds |
|
118
|
+
./spec/pec_ruby_spec.rb[1:2:5] | passed | 0.00002 seconds |
|
data/CHANGELOG.md
CHANGED
@@ -5,7 +5,44 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
-
## [
|
8
|
+
## [0.2.2] - 2025-07-13
|
9
|
+
|
10
|
+
### Fixed
|
11
|
+
- **CLI body display bug**: Fixed `NoMethodError` when displaying message body in CLI where `original_body` hash was treated as string
|
12
|
+
- **Message ordering in CLI**: Fixed message sorting to properly show newest messages first by date instead of sequence number
|
13
|
+
|
14
|
+
### Changed
|
15
|
+
- **CLI improvements**: Increased message limit from 20 to 50 messages for better user experience
|
16
|
+
- **Text formatting**: Enhanced body text formatting with smart quote normalization and line ending cleanup
|
17
|
+
|
18
|
+
### Added
|
19
|
+
- Better text readability in CLI with automatic formatting improvements
|
20
|
+
- Proper handling of different character encodings in message body display
|
21
|
+
|
22
|
+
## [0.2.1] - 2025-07-13
|
23
|
+
|
24
|
+
### Fixed
|
25
|
+
- **Fixed forwarded postacert.eml detection**: Now correctly detects and processes postacert.eml files that are forwarded as attachments in nested MESSAGE/RFC822 structures
|
26
|
+
- Improved nested postacert part ID detection algorithm to handle complex IMAP message structures
|
27
|
+
|
28
|
+
### Added
|
29
|
+
- Comprehensive test suite for nested postacert detection scenarios
|
30
|
+
- Performance optimizations with memoization for attachment calculations
|
31
|
+
- Enhanced error handling for malformed IMAP structures
|
32
|
+
- Support for environment variable configuration (`PEC_HOST`, `PEC_USERNAME`, `PEC_PASSWORD`)
|
33
|
+
- Security improvements to prevent credential leaks in test files
|
34
|
+
|
35
|
+
### Changed
|
36
|
+
- **Code refactoring**: Unified duplicate postacert detection methods into single parameterized method
|
37
|
+
- **Performance**: Added memoization to `original_attachments`, `nested_postacerts`, and `nested_postacert_attachments` methods
|
38
|
+
- **Security**: Test files now use environment variables instead of hardcoded credentials
|
39
|
+
- Improved robustness of bodystructure parsing with defensive programming techniques
|
40
|
+
|
41
|
+
### Security
|
42
|
+
- Removed all hardcoded credentials from test files
|
43
|
+
- Added `.env.example` for secure configuration
|
44
|
+
- Enhanced `.gitignore` to prevent accidental credential commits
|
45
|
+
- Added security documentation in README
|
9
46
|
|
10
47
|
## [0.2.0] - 2025-07-13
|
11
48
|
|
@@ -59,6 +96,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
59
96
|
- Aruba PEC (imaps.pec.aruba.it)
|
60
97
|
- Generic IMAP-compliant PEC providers
|
61
98
|
|
62
|
-
[Unreleased]: https://github.com/egio12/pec_ruby/compare/v0.2.
|
99
|
+
[Unreleased]: https://github.com/egio12/pec_ruby/compare/v0.2.2...HEAD
|
100
|
+
[0.2.2]: https://github.com/egio12/pec_ruby/compare/v0.2.1...v0.2.2
|
101
|
+
[0.2.1]: https://github.com/egio12/pec_ruby/compare/v0.2.0...v0.2.1
|
63
102
|
[0.2.0]: https://github.com/egio12/pec_ruby/compare/v0.1.0...v0.2.0
|
64
103
|
[0.1.0]: https://github.com/egio12/pec_ruby/releases/tag/v0.1.0
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -6,9 +6,12 @@ A comprehensive Ruby gem for decoding and managing Italian PEC (Posta Elettronic
|
|
6
6
|
|
7
7
|
- **IMAP Connection**: Connect to Italian PEC servers
|
8
8
|
- **Automatic Extraction**: Automatically extracts original messages from postacert.eml attachments
|
9
|
+
- **Nested PEC Support**: **NEW in v0.2.1** - Detects and processes forwarded PEC messages (nested postacert.eml files)
|
9
10
|
- **Attachment Management**: Download and manage attachments easily
|
11
|
+
- **Performance Optimized**: **NEW in v0.2.1** - Memoization for faster repeated access to attachments
|
10
12
|
- **CLI Included**: Command-line interface for exploring PEC messages
|
11
13
|
- **Programmatic API**: Methods for integrating PEC functionality into your Ruby applications
|
14
|
+
- **Comprehensive Testing**: Full test suite with both unit and integration tests
|
12
15
|
|
13
16
|
## Installation
|
14
17
|
|
@@ -57,6 +60,8 @@ The CLI allows you to:
|
|
57
60
|
- Explore received messages
|
58
61
|
- View decoded original message contents
|
59
62
|
- Download attachments
|
63
|
+
- **NEW in v0.2.1**: Detect and process forwarded PEC messages (nested postacert.eml files)
|
64
|
+
- **NEW in v0.2.1**: Enhanced performance with memoization for large attachments
|
60
65
|
|
61
66
|
## Programmatic Usage
|
62
67
|
|
@@ -149,6 +154,15 @@ PecRuby::Client.new(host:, username:, password:, ssl: true)
|
|
149
154
|
- `password` (String): Account password
|
150
155
|
- `ssl` (Boolean): Use SSL connection (default: true)
|
151
156
|
|
157
|
+
> **Security Note**: For production usage, consider using environment variables instead of hardcoding credentials:
|
158
|
+
> ```ruby
|
159
|
+
> client = PecRuby::Client.new(
|
160
|
+
> host: ENV['PEC_HOST'],
|
161
|
+
> username: ENV['PEC_USERNAME'],
|
162
|
+
> password: ENV['PEC_PASSWORD']
|
163
|
+
> )
|
164
|
+
> ```
|
165
|
+
|
152
166
|
#### Instance Methods
|
153
167
|
|
154
168
|
##### `#connect`
|
@@ -423,6 +437,41 @@ ensure
|
|
423
437
|
end
|
424
438
|
```
|
425
439
|
|
440
|
+
### Nested PEC Detection Example (NEW in v0.2.1)
|
441
|
+
|
442
|
+
Handle forwarded PEC messages that contain other PEC messages as attachments:
|
443
|
+
|
444
|
+
```ruby
|
445
|
+
# Find a message with forwarded PECs
|
446
|
+
message = client.pec_messages.find { |msg| msg.has_nested_postacerts? }
|
447
|
+
|
448
|
+
if message
|
449
|
+
puts "Found message with #{message.nested_postacerts.size} forwarded PEC(s):"
|
450
|
+
|
451
|
+
# Process each forwarded PEC
|
452
|
+
message.nested_postacert_messages.each_with_index do |nested_msg, index|
|
453
|
+
puts " Forwarded PEC ##{index + 1}:"
|
454
|
+
puts " Subject: #{nested_msg.subject}"
|
455
|
+
puts " From: #{nested_msg.from}"
|
456
|
+
puts " Date: #{nested_msg.date}"
|
457
|
+
puts " Attachments: #{nested_msg.attachments.size}"
|
458
|
+
|
459
|
+
# Download attachments from the forwarded PEC
|
460
|
+
nested_msg.attachments.each do |attachment|
|
461
|
+
unless attachment.postacert? # Avoid infinite recursion
|
462
|
+
attachment.save_to_dir('./downloads/forwarded')
|
463
|
+
puts " Downloaded: #{attachment.filename}"
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
# Check for even deeper nesting (PEC forwarded within forwarded PEC)
|
468
|
+
if nested_msg.has_nested_postacerts?
|
469
|
+
puts " -> Contains #{nested_msg.nested_postacerts.size} more forwarded PEC(s)!"
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
```
|
474
|
+
|
426
475
|
## Error Handling
|
427
476
|
|
428
477
|
The gem defines several specific error classes:
|
@@ -463,6 +512,46 @@ Other providers should work if they support standard IMAP, but have not been tes
|
|
463
512
|
- **Provider Testing**: Only tested with Aruba PEC. Other providers may work but are not guaranteed.
|
464
513
|
- **Legal Compliance**: This library has not been evaluated for compliance with Italian PEC regulations or legal requirements. The message parsing methods used may not preserve all legally required aspects of certified email messages. Users should consult with legal experts and review applicable regulations before using this library in legally sensitive contexts.
|
465
514
|
|
515
|
+
## Testing & Development Configuration
|
516
|
+
|
517
|
+
### Environment Variables
|
518
|
+
|
519
|
+
For security, use environment variables to configure your PEC credentials:
|
520
|
+
|
521
|
+
```bash
|
522
|
+
# Copy the example environment file
|
523
|
+
cp .env.example .env
|
524
|
+
|
525
|
+
# Edit .env with your actual credentials
|
526
|
+
export PEC_HOST=imaps.pec.aruba.it
|
527
|
+
export PEC_USERNAME=your@domain.pec.it
|
528
|
+
export PEC_PASSWORD=your_password
|
529
|
+
export PEC_TEST_UID=1234 # Optional: specific message UID for testing
|
530
|
+
```
|
531
|
+
|
532
|
+
### Running Tests
|
533
|
+
|
534
|
+
The gem includes comprehensive tests for all functionality:
|
535
|
+
|
536
|
+
```bash
|
537
|
+
bundle install
|
538
|
+
|
539
|
+
# Run all tests (will skip integration tests without PEC credentials)
|
540
|
+
bundle exec rspec
|
541
|
+
|
542
|
+
# Run with PEC credentials for full integration testing
|
543
|
+
PEC_HOST=imaps.pec.aruba.it PEC_USERNAME=your@domain.pec.it PEC_PASSWORD=your_password bundle exec rspec
|
544
|
+
|
545
|
+
# Run specific test suites
|
546
|
+
bundle exec rspec spec/pec_ruby/nested_postacert_spec.rb # Nested PEC detection tests
|
547
|
+
bundle exec rspec spec/pec_ruby/message_refactoring_spec.rb # Performance & refactoring tests
|
548
|
+
|
549
|
+
# Check code style
|
550
|
+
bundle exec rubocop
|
551
|
+
```
|
552
|
+
|
553
|
+
**Note**: Integration tests require real PEC credentials and will be skipped if environment variables are not set. Unit tests will always run.
|
554
|
+
|
466
555
|
## Development
|
467
556
|
|
468
557
|
After cloning the repository:
|
data/lib/pec_ruby/attachment.rb
CHANGED
@@ -197,4 +197,19 @@ module PecRuby
|
|
197
197
|
nil
|
198
198
|
end
|
199
199
|
end
|
200
|
+
|
201
|
+
# Simple wrapper for mail attachments that mimics Mail::Attachment interface
|
202
|
+
class SimpleMailAttachment
|
203
|
+
attr_reader :mail, :filename, :mime_type
|
204
|
+
|
205
|
+
def initialize(mail, filename, mime_type)
|
206
|
+
@mail = mail
|
207
|
+
@filename = filename
|
208
|
+
@mime_type = mime_type
|
209
|
+
end
|
210
|
+
|
211
|
+
def decoded
|
212
|
+
@mail.to_s
|
213
|
+
end
|
214
|
+
end
|
200
215
|
end
|
data/lib/pec_ruby/cli.rb
CHANGED
@@ -101,7 +101,9 @@ module PecRuby
|
|
101
101
|
puts "\nCaricamento messaggi..."
|
102
102
|
|
103
103
|
begin
|
104
|
-
messages = @client.pec_messages(limit:
|
104
|
+
messages = @client.pec_messages(limit: 50, reverse: false)
|
105
|
+
# Sort by date in descending order (newest first)
|
106
|
+
messages = messages.sort_by { |msg| msg.date || Time.at(0) }.reverse
|
105
107
|
|
106
108
|
if messages.empty?
|
107
109
|
puts "Nessun messaggio PEC trovato"
|
@@ -161,10 +163,19 @@ module PecRuby
|
|
161
163
|
|
162
164
|
# Corpo del messaggio
|
163
165
|
body = message.original_body
|
164
|
-
if body && !body.strip.empty?
|
166
|
+
if body && body[:content] && !body[:content].strip.empty?
|
165
167
|
puts "\nCORPO DEL MESSAGGIO"
|
166
168
|
puts "─"*50
|
167
|
-
|
169
|
+
|
170
|
+
# Format the body for better readability
|
171
|
+
content = body[:content].strip
|
172
|
+
|
173
|
+
# Clean up common formatting issues
|
174
|
+
content = content.gsub(/\r\n/, "\n") # Normalize line endings
|
175
|
+
content = content.gsub(/\u0093|\u0094/, '"') # Replace smart quotes
|
176
|
+
content = content.gsub(/\u0092/, "'") # Replace smart apostrophes
|
177
|
+
|
178
|
+
puts content
|
168
179
|
end
|
169
180
|
|
170
181
|
# Allegati
|
data/lib/pec_ruby/message.rb
CHANGED
@@ -148,12 +148,23 @@ module PecRuby
|
|
148
148
|
raw_body.dup.force_encoding(charset).encode("UTF-8")
|
149
149
|
end
|
150
150
|
|
151
|
-
# Get original message attachments
|
151
|
+
# Get original message attachments (with memoization)
|
152
152
|
def original_attachments
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
153
|
+
@original_attachments ||= begin
|
154
|
+
mail = postacert_message
|
155
|
+
attachments = []
|
156
|
+
|
157
|
+
# Add attachments from the original message
|
158
|
+
if mail&.attachments
|
159
|
+
attachments += mail.attachments.map { |att| Attachment.new(att) }
|
160
|
+
end
|
161
|
+
|
162
|
+
# Also check for postacert.eml attachments in the outer message structure
|
163
|
+
# This handles cases where postacert.eml files are forwarded as attachments
|
164
|
+
attachments += nested_postacert_attachments
|
165
|
+
|
166
|
+
attachments
|
167
|
+
end
|
157
168
|
end
|
158
169
|
|
159
170
|
# Get original message attachments that are NOT postacert.eml files
|
@@ -163,7 +174,7 @@ module PecRuby
|
|
163
174
|
|
164
175
|
# Get nested postacert.eml files from original message attachments
|
165
176
|
def nested_postacerts
|
166
|
-
original_attachments.select(&:postacert?)
|
177
|
+
@nested_postacerts ||= original_attachments.select(&:postacert?)
|
167
178
|
end
|
168
179
|
|
169
180
|
# Check if original message has nested postacert.eml files
|
@@ -256,36 +267,67 @@ module PecRuby
|
|
256
267
|
email
|
257
268
|
end
|
258
269
|
|
259
|
-
def
|
270
|
+
def nested_postacert_attachments
|
271
|
+
@nested_postacert_attachments ||= begin
|
272
|
+
attachments = []
|
273
|
+
|
274
|
+
# Find all postacert.eml parts (including nested)
|
275
|
+
all_postacert_part_ids = find_postacert_part_ids(@bodystructure, "", true)
|
276
|
+
main_postacert_part_id = find_postacert_part_ids.first
|
277
|
+
|
278
|
+
# Add any postacert.eml parts that are not the main one as attachments
|
279
|
+
nested_postacert_part_ids = all_postacert_part_ids - [main_postacert_part_id]
|
280
|
+
|
281
|
+
nested_postacert_part_ids.each do |part_id|
|
282
|
+
begin
|
283
|
+
raw_data = @client.fetch_body_part(@uid, part_id)
|
284
|
+
mail_data = Mail.read_from_string(raw_data)
|
285
|
+
|
286
|
+
# Create a simplified attachment wrapper
|
287
|
+
wrapper = SimpleMailAttachment.new(mail_data, "postacert.eml", "message/rfc822")
|
288
|
+
attachments << Attachment.new(wrapper)
|
289
|
+
rescue => e
|
290
|
+
puts "Warning: Failed to extract nested postacert.eml at #{part_id}: #{e.message}"
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
attachments
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
def find_postacert_part_ids(bodystructure = @bodystructure, path = "", include_nested = false)
|
260
300
|
results = []
|
301
|
+
|
302
|
+
return results unless bodystructure
|
261
303
|
|
262
304
|
if bodystructure.respond_to?(:parts) && bodystructure.parts
|
263
305
|
bodystructure.parts.each_with_index do |part, index|
|
264
306
|
part_path = path.empty? ? "#{index + 1}" : "#{path}.#{index + 1}"
|
265
|
-
results += find_postacert_part_ids(part, part_path)
|
307
|
+
results += find_postacert_part_ids(part, part_path, include_nested)
|
266
308
|
end
|
267
|
-
elsif bodystructure.media_type
|
268
|
-
|
309
|
+
elsif bodystructure.respond_to?(:media_type) && bodystructure.media_type == "MESSAGE" &&
|
310
|
+
bodystructure.respond_to?(:subtype) && bodystructure.subtype == "RFC822"
|
311
|
+
if bodystructure.respond_to?(:param) && bodystructure.param &&
|
312
|
+
bodystructure.param["NAME"]&.downcase&.include?("postacert.eml")
|
269
313
|
results << path
|
270
314
|
end
|
315
|
+
|
316
|
+
# Search inside MESSAGE/RFC822 bodies for nested postacert.eml files if requested
|
317
|
+
if include_nested && bodystructure.respond_to?(:body) && bodystructure.body&.respond_to?(:parts)
|
318
|
+
bodystructure.body.parts.each_with_index do |nested_part, nested_index|
|
319
|
+
nested_path = "#{path}.#{nested_index + 1}"
|
320
|
+
results += find_postacert_part_ids(nested_part, nested_path, include_nested)
|
321
|
+
end
|
322
|
+
end
|
271
323
|
end
|
272
324
|
|
273
325
|
results
|
274
326
|
end
|
275
327
|
|
328
|
+
# Delegate to the shared implementation in NestedPostacertMessage
|
276
329
|
def extract_text_part(mail, preferred_type = "text/plain")
|
277
|
-
|
278
|
-
|
279
|
-
mail.parts.each do |part|
|
280
|
-
if part.multipart?
|
281
|
-
found = extract_text_part(part, preferred_type)
|
282
|
-
return found if found
|
283
|
-
elsif part.mime_type == preferred_type
|
284
|
-
return part
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
nil
|
330
|
+
NestedPostacertMessage.new(mail).send(:extract_text_part, mail, preferred_type)
|
289
331
|
end
|
290
332
|
end
|
291
333
|
end
|
data/lib/pec_ruby/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pec_ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- EMG
|
@@ -67,8 +67,9 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.0'
|
69
69
|
description: A comprehensive Ruby library for handling Italian certified email (PEC)
|
70
|
-
messages.
|
71
|
-
and a CLI for exploring PEC messages.
|
70
|
+
messages. Supports nested PEC detection, extracting postacert.eml contents, attachment
|
71
|
+
management, and includes a CLI for exploring PEC messages. Features performance
|
72
|
+
optimizations and secure credential handling.
|
72
73
|
email:
|
73
74
|
- enricomaria.giordano@icloud.com
|
74
75
|
executables:
|
@@ -76,6 +77,7 @@ executables:
|
|
76
77
|
extensions: []
|
77
78
|
extra_rdoc_files: []
|
78
79
|
files:
|
80
|
+
- ".env.example"
|
79
81
|
- ".rspec"
|
80
82
|
- ".rspec_status"
|
81
83
|
- CHANGELOG.md
|
@@ -91,7 +93,6 @@ files:
|
|
91
93
|
- lib/pec_ruby/client.rb
|
92
94
|
- lib/pec_ruby/message.rb
|
93
95
|
- lib/pec_ruby/version.rb
|
94
|
-
- pec_ruby.gemspec
|
95
96
|
homepage: https://github.com/egio12/pec_ruby
|
96
97
|
licenses:
|
97
98
|
- MIT
|
data/pec_ruby.gemspec
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "lib/pec_ruby/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "pec_ruby"
|
7
|
-
spec.version = PecRuby::VERSION
|
8
|
-
spec.authors = ["EMG"]
|
9
|
-
spec.email = ["enricomaria.giordano@icloud.com"]
|
10
|
-
|
11
|
-
spec.summary = "Ruby gem for decoding and reading Italian PEC (Posta Elettronica Certificata) emails"
|
12
|
-
spec.description = "A comprehensive Ruby library for handling Italian certified email (PEC) messages. Includes methods for extracting postacert.eml contents, decoding attachments, and a CLI for exploring PEC messages."
|
13
|
-
spec.homepage = "https://github.com/egio12/pec_ruby"
|
14
|
-
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 2.6.0"
|
16
|
-
|
17
|
-
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
18
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
-
spec.metadata["source_code_uri"] = "https://github.com/egio12/pec_ruby"
|
20
|
-
spec.metadata["changelog_uri"] = "https://github.com/egio12/pec_ruby/blob/main/CHANGELOG.md"
|
21
|
-
|
22
|
-
# Specify which files should be added to the gem when it is released.
|
23
|
-
spec.files = Dir.chdir(__dir__) do
|
24
|
-
`git ls-files -z 2>/dev/null`.split("\x0").reject do |f|
|
25
|
-
(f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
26
|
-
end
|
27
|
-
end
|
28
|
-
spec.bindir = "bin"
|
29
|
-
spec.executables = ["pec_ruby"]
|
30
|
-
spec.require_paths = ["lib"]
|
31
|
-
|
32
|
-
# Core dependencies
|
33
|
-
spec.add_dependency "mail", "~> 2.7"
|
34
|
-
spec.add_dependency "net-imap", "~> 0.3"
|
35
|
-
|
36
|
-
# Development dependencies
|
37
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
38
|
-
spec.add_development_dependency "rubocop", "~> 1.0"
|
39
|
-
end
|