pec_ruby 0.2.2 → 0.2.3
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/.rspec_status +109 -92
- data/CHANGELOG.md +36 -0
- data/Gemfile.lock +3 -1
- data/README.md +212 -45
- data/lib/pec_ruby/cli.rb +353 -111
- data/lib/pec_ruby/client.rb +77 -29
- data/lib/pec_ruby/message.rb +188 -38
- data/lib/pec_ruby/version.rb +2 -2
- data/lib/pec_ruby.rb +7 -6
- metadata +16 -2
data/README.md
CHANGED
@@ -9,6 +9,9 @@ A comprehensive Ruby gem for decoding and managing Italian PEC (Posta Elettronic
|
|
9
9
|
- **Nested PEC Support**: **NEW in v0.2.1** - Detects and processes forwarded PEC messages (nested postacert.eml files)
|
10
10
|
- **Attachment Management**: Download and manage attachments easily
|
11
11
|
- **Performance Optimized**: **NEW in v0.2.1** - Memoization for faster repeated access to attachments
|
12
|
+
- **Ruby Way Behavior**: **NEW in v0.2.3** - Intuitive method behavior where `subject/from/to/date` always return the most relevant content
|
13
|
+
- **Smart Body Access**: **NEW in v0.2.3** - Universal body access methods work with both received and sent messages
|
14
|
+
- **Folder Management**: **NEW in v0.2.3** - Easy navigation and selection of PEC folders (INBOX, sent, drafts, etc.)
|
12
15
|
- **CLI Included**: Command-line interface for exploring PEC messages
|
13
16
|
- **Programmatic API**: Methods for integrating PEC functionality into your Ruby applications
|
14
17
|
- **Comprehensive Testing**: Full test suite with both unit and integration tests
|
@@ -42,6 +45,7 @@ Or in your Gemfile:
|
|
42
45
|
```ruby
|
43
46
|
gem 'pec_ruby'
|
44
47
|
gem 'tty-prompt', '~> 0.23'
|
48
|
+
gem 'tty-screen', '~> 0.8'
|
45
49
|
gem 'awesome_print', '~> 1.9'
|
46
50
|
```
|
47
51
|
|
@@ -55,14 +59,53 @@ pec_ruby
|
|
55
59
|
|
56
60
|
**Note**: If you installed only the library without CLI dependencies, the `pec_ruby` executable will inform you how to install them.
|
57
61
|
|
62
|
+
**CLI Dependencies:**
|
63
|
+
- `tty-prompt` (~> 0.23) - Interactive menus and prompts
|
64
|
+
- `tty-screen` (~> 0.8) - Screen management and layout
|
65
|
+
- `awesome_print` (~> 1.9) - Enhanced object printing
|
66
|
+
|
58
67
|
The CLI allows you to:
|
59
68
|
- Connect to your PEC server
|
60
|
-
-
|
69
|
+
- **NEW in v0.2.3**: Select and switch between different folders (INBOX, Sent, etc.)
|
70
|
+
- Explore received messages with Ruby Way behavior (most relevant content displayed first)
|
61
71
|
- View decoded original message contents
|
62
72
|
- Download attachments
|
63
73
|
- **NEW in v0.2.1**: Detect and process forwarded PEC messages (nested postacert.eml files)
|
64
74
|
- **NEW in v0.2.1**: Enhanced performance with memoization for large attachments
|
65
75
|
|
76
|
+
### CLI Workflow (v0.2.3)
|
77
|
+
|
78
|
+
The CLI now features a **professional, full-screen interface** with enhanced performance and user experience:
|
79
|
+
|
80
|
+
**🚀 Performance Improvements:**
|
81
|
+
- **Optimized IMAP fetching**: Messages load in ~0.2s instead of several seconds
|
82
|
+
- **Smart envelope caching**: List view uses only envelope data (no postacert fetching)
|
83
|
+
- **Batch processing**: Efficient handling of large mailboxes
|
84
|
+
- **On-demand loading**: Full message details fetched only when selected
|
85
|
+
|
86
|
+
**🎨 Enhanced Interface:**
|
87
|
+
- **Fixed header**: Banner and status always visible
|
88
|
+
- **Clean screen management**: No scrolling, professional layout
|
89
|
+
- **Interactive message viewer**: Menu-driven navigation with options
|
90
|
+
- **Progress indicators**: Real-time feedback for all operations
|
91
|
+
- **Folder management**: Easy switching between INBOX, Sent, Trash, etc.
|
92
|
+
|
93
|
+
**📋 Complete Workflow:**
|
94
|
+
1. **Connect** to your PEC server with credential validation
|
95
|
+
2. **Select folder** from available options (INBOX, Sent, drafts, etc.)
|
96
|
+
3. **Browse messages** with fast envelope-based listing
|
97
|
+
4. **Message details** with interactive menu:
|
98
|
+
- View complete message body
|
99
|
+
- Download attachments with progress tracking
|
100
|
+
- Navigate between Ruby Way and PEC envelope data
|
101
|
+
5. **Attachment management** with visual progress and batch download
|
102
|
+
|
103
|
+
**Main Menu Options:**
|
104
|
+
- **Connect to PEC server**: Secure login with connection status
|
105
|
+
- **Select folder**: Visual folder picker with current selection indicator
|
106
|
+
- **List and analyze messages**: Fast message browsing with timing information
|
107
|
+
- **Disconnect**: Clean logout with confirmation
|
108
|
+
|
66
109
|
## Programmatic Usage
|
67
110
|
|
68
111
|
### Basic Connection
|
@@ -87,7 +130,7 @@ client.connect
|
|
87
130
|
messages = client.messages(limit: 10)
|
88
131
|
|
89
132
|
# Only PEC messages (with postacert.eml)
|
90
|
-
|
133
|
+
messages = client.messages(limit: 10)
|
91
134
|
|
92
135
|
# Specific message by UID
|
93
136
|
message = client.message(12345)
|
@@ -96,7 +139,7 @@ message = client.message(12345)
|
|
96
139
|
### Working with Messages
|
97
140
|
|
98
141
|
```ruby
|
99
|
-
message = client.
|
142
|
+
message = client.messages.first
|
100
143
|
|
101
144
|
# PEC container information
|
102
145
|
puts message.subject # PEC message subject
|
@@ -190,6 +233,33 @@ client.connected?
|
|
190
233
|
# Returns: Boolean
|
191
234
|
```
|
192
235
|
|
236
|
+
##### `#available_folders` (NEW in v0.2.3)
|
237
|
+
Lists all available folders in the mailbox.
|
238
|
+
|
239
|
+
```ruby
|
240
|
+
folders = client.available_folders
|
241
|
+
# Returns: Array<String>
|
242
|
+
# Example: ["INBOX", "INBOX.inviata", "INBOX.bozze", "INBOX.cestino"]
|
243
|
+
```
|
244
|
+
|
245
|
+
##### `#select_folder(folder)` (NEW in v0.2.3)
|
246
|
+
Selects a specific folder for operations.
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
client.select_folder('INBOX.inviata')
|
250
|
+
# Returns: Net::IMAP response
|
251
|
+
# Raises: PecRuby::FolderError if folder doesn't exist
|
252
|
+
```
|
253
|
+
|
254
|
+
##### `#select_inbox` (NEW in v0.2.3)
|
255
|
+
Convenience method to select the INBOX folder.
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
client.select_inbox
|
259
|
+
# Returns: Net::IMAP response
|
260
|
+
# Raises: PecRuby::FolderError if INBOX doesn't exist
|
261
|
+
```
|
262
|
+
|
193
263
|
##### `#messages(limit: nil, reverse: true)`
|
194
264
|
Retrieves messages from the server.
|
195
265
|
|
@@ -202,13 +272,6 @@ messages = client.messages(limit: 10, reverse: true)
|
|
202
272
|
- `limit` (Integer, optional): Maximum number of messages to retrieve
|
203
273
|
- `reverse` (Boolean): Return newest messages first (default: true)
|
204
274
|
|
205
|
-
##### `#pec_messages(limit: nil, reverse: true)`
|
206
|
-
Retrieves only messages containing postacert.eml.
|
207
|
-
|
208
|
-
```ruby
|
209
|
-
pec_messages = client.pec_messages(limit: 5)
|
210
|
-
# Returns: Array<PecRuby::Message>
|
211
|
-
```
|
212
275
|
|
213
276
|
##### `#message(uid)`
|
214
277
|
Retrieves a specific message by UID.
|
@@ -224,39 +287,65 @@ Represents a PEC message with access to both container and original message data
|
|
224
287
|
|
225
288
|
#### Instance Methods
|
226
289
|
|
227
|
-
#####
|
290
|
+
##### Ruby Way Behavior - Most Relevant Content (NEW in v0.2.3)
|
228
291
|
|
229
292
|
```ruby
|
230
|
-
#
|
293
|
+
# These methods return the most relevant content:
|
294
|
+
# - postacert.eml content if available (received messages)
|
295
|
+
# - direct message content if no postacert.eml (sent messages)
|
231
296
|
message.uid # Integer: Message UID
|
232
|
-
message.subject # String:
|
233
|
-
message.from # String:
|
234
|
-
message.to # Array<String>:
|
235
|
-
message.date # Time:
|
297
|
+
message.subject # String: Most relevant subject
|
298
|
+
message.from # String: Most relevant sender
|
299
|
+
message.to # Array<String>: Most relevant recipients
|
300
|
+
message.date # Time: Most relevant message date
|
301
|
+
message.has_postacert? # Boolean: Check if postacert.eml is available
|
236
302
|
```
|
237
303
|
|
238
|
-
#####
|
304
|
+
##### PEC Container Access
|
239
305
|
|
240
306
|
```ruby
|
241
|
-
#
|
242
|
-
message.
|
307
|
+
# These methods always return the outer PEC container information
|
308
|
+
message.original_subject # String: PEC envelope subject (cleaned)
|
309
|
+
message.original_from # String: PEC envelope sender
|
310
|
+
message.original_to # Array<String>: PEC envelope recipients
|
311
|
+
message.original_date # Time: PEC envelope date
|
312
|
+
```
|
243
313
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
message.
|
249
|
-
message.
|
250
|
-
message.
|
251
|
-
|
314
|
+
##### Postacert.eml Access
|
315
|
+
|
316
|
+
```ruby
|
317
|
+
# Direct access to postacert.eml content (nil if not available)
|
318
|
+
message.postacert_body # Hash: Postacert message body with format info
|
319
|
+
message.postacert_body_text # String: Plain text body only
|
320
|
+
message.postacert_body_html # String: HTML body only
|
321
|
+
|
322
|
+
# Legacy aliases for backward compatibility
|
323
|
+
message.original_body # Hash: Alias for postacert_body
|
324
|
+
message.original_body_text # String: Alias for postacert_body_text
|
325
|
+
message.original_body_html # String: Alias for postacert_body_html
|
252
326
|
```
|
253
327
|
|
254
|
-
#####
|
328
|
+
##### Smart Message Body Access (NEW in v0.2.3)
|
329
|
+
|
330
|
+
```ruby
|
331
|
+
# Smart body access - works with both received and sent messages
|
332
|
+
message.raw_body # Hash: Body with format info (postacert.eml if available, otherwise direct message)
|
333
|
+
message.raw_body_text # String: Plain text body (postacert.eml if available, otherwise direct message)
|
334
|
+
message.raw_body_html # String: HTML body (postacert.eml if available, otherwise direct message)
|
335
|
+
```
|
336
|
+
|
337
|
+
**Behavior:**
|
338
|
+
- For received messages (with postacert.eml): Returns content from postacert.eml (same as `original_*` methods)
|
339
|
+
- For sent messages (without postacert.eml): Returns content from the message itself
|
340
|
+
- **Recommended**: Use `raw_body_*` methods for universal compatibility
|
341
|
+
|
342
|
+
##### Message Body Handling
|
255
343
|
|
256
|
-
|
344
|
+
Both `original_body` and `raw_body` methods return a hash with format information, allowing you to handle different content types appropriately:
|
257
345
|
|
258
346
|
```ruby
|
259
|
-
|
347
|
+
# Use raw_body for universal compatibility (recommended)
|
348
|
+
body_info = message.raw_body
|
260
349
|
if body_info
|
261
350
|
puts "Content type: #{body_info[:content_type]}"
|
262
351
|
puts "Charset: #{body_info[:charset]}"
|
@@ -274,16 +363,24 @@ if body_info
|
|
274
363
|
end
|
275
364
|
|
276
365
|
# Or use convenience methods for specific formats
|
277
|
-
text_only = message.
|
278
|
-
html_only = message.
|
366
|
+
text_only = message.raw_body_text # Works for both received and sent messages
|
367
|
+
html_only = message.raw_body_html # Works for both received and sent messages
|
368
|
+
|
369
|
+
# Use original_* methods only when you specifically need postacert.eml content
|
370
|
+
original_text = message.original_body_text # Returns nil if no postacert.eml
|
371
|
+
original_html = message.original_body_html # Returns nil if no postacert.eml
|
279
372
|
```
|
280
373
|
|
281
374
|
##### Attachments
|
282
375
|
|
283
376
|
```ruby
|
284
|
-
#
|
285
|
-
message.
|
286
|
-
message.
|
377
|
+
# Smart attachment access - returns most relevant attachments
|
378
|
+
message.attachments # Array<PecRuby::Attachment> - Smart attachment access
|
379
|
+
message.regular_attachments # Array<PecRuby::Attachment> - Non-postacert attachments only
|
380
|
+
|
381
|
+
# Direct postacert.eml attachment access
|
382
|
+
message.postacert_attachments # Array<PecRuby::Attachment> - All postacert attachments
|
383
|
+
message.postacert_regular_attachments # Array<PecRuby::Attachment> - Non-postacert attachments only
|
287
384
|
message.nested_postacerts # Array<PecRuby::Attachment> - Nested postacert.eml files only
|
288
385
|
|
289
386
|
# Check for nested postacerts (forwarded PECs)
|
@@ -292,6 +389,10 @@ message.nested_postacert_messages # Array<PecRuby::NestedPostacertMessage>
|
|
292
389
|
|
293
390
|
# Get all postacert messages in a flattened structure
|
294
391
|
message.all_postacert_messages # Array<Hash> - Hierarchical view of all messages
|
392
|
+
|
393
|
+
# Legacy aliases for backward compatibility
|
394
|
+
message.original_attachments # Array<PecRuby::Attachment> - Alias for postacert_attachments
|
395
|
+
message.original_regular_attachments # Array<PecRuby::Attachment> - Alias for postacert_regular_attachments
|
295
396
|
```
|
296
397
|
|
297
398
|
##### Summary Information
|
@@ -374,17 +475,19 @@ begin
|
|
374
475
|
client.connect
|
375
476
|
|
376
477
|
# Get last 5 PEC messages
|
377
|
-
|
478
|
+
messages = client.messages(limit: 5)
|
378
479
|
|
379
|
-
|
380
|
-
|
381
|
-
puts "
|
382
|
-
puts "
|
383
|
-
puts "
|
480
|
+
messages.each do |message|
|
481
|
+
# Ruby Way - these methods automatically return the most relevant content
|
482
|
+
puts "Subject: #{message.subject}" # Postacert.eml subject if available, otherwise PEC envelope
|
483
|
+
puts "From: #{message.from}" # Postacert.eml sender if available, otherwise PEC envelope
|
484
|
+
puts "Date: #{message.date}" # Postacert.eml date if available, otherwise PEC envelope
|
485
|
+
puts "Total attachments: #{message.attachments.size}"
|
486
|
+
puts "Regular attachments: #{message.regular_attachments.size}"
|
384
487
|
puts "Nested PECs: #{message.nested_postacerts.size}"
|
385
488
|
|
386
|
-
# Handle message body based on format
|
387
|
-
body_info = message.
|
489
|
+
# Handle message body based on format - use raw_body for universal compatibility
|
490
|
+
body_info = message.raw_body
|
388
491
|
if body_info
|
389
492
|
puts "Body format: #{body_info[:content_type]}"
|
390
493
|
case body_info[:content_type]
|
@@ -399,7 +502,7 @@ begin
|
|
399
502
|
end
|
400
503
|
|
401
504
|
# Download regular attachments
|
402
|
-
message.
|
505
|
+
message.regular_attachments.each do |attachment|
|
403
506
|
attachment.save_to_dir('./downloads')
|
404
507
|
puts "Downloaded: #{attachment.filename}"
|
405
508
|
end
|
@@ -437,13 +540,76 @@ ensure
|
|
437
540
|
end
|
438
541
|
```
|
439
542
|
|
543
|
+
### Ruby Way Behavior Change (v0.2.3)
|
544
|
+
|
545
|
+
**Important**: In v0.2.3, we've changed the behavior of core methods to be more intuitive and "Ruby Way":
|
546
|
+
|
547
|
+
```ruby
|
548
|
+
# OLD behavior (v0.2.2 and earlier)
|
549
|
+
message.subject # → Always PEC envelope subject
|
550
|
+
message.original_subject # → Postacert.eml subject (if available)
|
551
|
+
|
552
|
+
# NEW behavior (v0.2.3 and later) - Ruby Way
|
553
|
+
message.subject # → Postacert.eml subject if available, otherwise PEC envelope
|
554
|
+
message.original_subject # → Always PEC envelope subject
|
555
|
+
```
|
556
|
+
|
557
|
+
**Migration**: Most code will continue to work, but if you specifically need PEC envelope data, use `original_*` methods. For postacert.eml data, use `postacert_*` methods or the legacy `original_*` aliases.
|
558
|
+
|
559
|
+
### Working with Different Folders (NEW in v0.2.3)
|
560
|
+
|
561
|
+
The gem now supports easy folder navigation:
|
562
|
+
|
563
|
+
```ruby
|
564
|
+
# List all available folders
|
565
|
+
folders = client.available_folders
|
566
|
+
puts "Available folders: #{folders.join(', ')}"
|
567
|
+
# Output: Available folders: INBOX, INBOX.inviata, INBOX.bozze, INBOX.cestino
|
568
|
+
|
569
|
+
# Select a specific folder
|
570
|
+
client.select_folder('INBOX.inviata')
|
571
|
+
# or use the convenience method for INBOX
|
572
|
+
client.select_inbox
|
573
|
+
|
574
|
+
# Get messages from the selected folder
|
575
|
+
messages = client.messages(limit: 10)
|
576
|
+
```
|
577
|
+
|
578
|
+
### Working with Sent Messages
|
579
|
+
|
580
|
+
The `raw_body_*` methods work seamlessly with sent messages (which don't have postacert.eml):
|
581
|
+
|
582
|
+
```ruby
|
583
|
+
# Get sent messages using the new folder methods
|
584
|
+
client.select_folder('INBOX.inviata')
|
585
|
+
sent_messages = client.messages(limit: 5)
|
586
|
+
|
587
|
+
sent_messages.each do |message|
|
588
|
+
puts "Subject: #{message.subject}"
|
589
|
+
puts "From: #{message.from}"
|
590
|
+
puts "Date: #{message.date}"
|
591
|
+
puts "Has postacert: #{message.has_postacert?}" # Will be false for sent messages
|
592
|
+
|
593
|
+
# Use raw_body methods for universal compatibility
|
594
|
+
body_text = message.raw_body_text
|
595
|
+
if body_text
|
596
|
+
puts "Body preview: #{body_text[0..100]}..."
|
597
|
+
end
|
598
|
+
|
599
|
+
# original_* methods will return nil for sent messages
|
600
|
+
puts "Original body: #{message.original_body_text.inspect}" # => nil
|
601
|
+
|
602
|
+
puts "─" * 40
|
603
|
+
end
|
604
|
+
```
|
605
|
+
|
440
606
|
### Nested PEC Detection Example (NEW in v0.2.1)
|
441
607
|
|
442
608
|
Handle forwarded PEC messages that contain other PEC messages as attachments:
|
443
609
|
|
444
610
|
```ruby
|
445
611
|
# Find a message with forwarded PECs
|
446
|
-
message = client.
|
612
|
+
message = client.messages.find { |msg| msg.has_nested_postacerts? }
|
447
613
|
|
448
614
|
if message
|
449
615
|
puts "Found message with #{message.nested_postacerts.size} forwarded PEC(s):"
|
@@ -482,6 +648,7 @@ PecRuby::ConnectionError # Connection issues
|
|
482
648
|
PecRuby::AuthenticationError # Login failures
|
483
649
|
PecRuby::MessageNotFoundError # Message not found
|
484
650
|
PecRuby::PostacertNotFoundError # postacert.eml not found
|
651
|
+
PecRuby::FolderError # Folder selection issues (NEW in v0.2.3)
|
485
652
|
```
|
486
653
|
|
487
654
|
Example with error handling:
|