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.
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
- - Explore received messages
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
- pec_messages = client.pec_messages(limit: 10)
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.pec_messages.first
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
- ##### Basic PEC Container Information
290
+ ##### Ruby Way Behavior - Most Relevant Content (NEW in v0.2.3)
228
291
 
229
292
  ```ruby
230
- # PEC envelope information
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: PEC subject (cleaned)
233
- message.from # String: PEC sender
234
- message.to # Array<String>: PEC recipients
235
- message.date # Time: PEC message date
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
- ##### Original Message Access
304
+ ##### PEC Container Access
239
305
 
240
306
  ```ruby
241
- # Check if postacert.eml is available
242
- message.has_postacert? # Boolean
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
- # Original message information
245
- message.original_subject # String: Original subject
246
- message.original_from # String: Original sender
247
- message.original_to # Array<String>: Original recipients
248
- message.original_date # Time: Original message date
249
- message.original_body # Hash: Original message body with format info
250
- message.original_body_text # String: Plain text body only
251
- message.original_body_html # String: HTML body only
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
- ##### Original Message Body
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
- The `original_body` method returns a hash with format information, allowing you to handle different content types appropriately:
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
- body_info = message.original_body
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.original_body_text # Returns nil if no text/plain part
278
- html_only = message.original_body_html # Returns nil if no text/html part
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
- # Get original message attachments
285
- message.original_attachments # Array<PecRuby::Attachment> - All attachments
286
- message.original_regular_attachments # Array<PecRuby::Attachment> - Non-postacert attachments only
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
- pec_messages = client.pec_messages(limit: 5)
478
+ messages = client.messages(limit: 5)
378
479
 
379
- pec_messages.each do |message|
380
- puts "Subject: #{message.original_subject}"
381
- puts "From: #{message.original_from}"
382
- puts "Total attachments: #{message.original_attachments.size}"
383
- puts "Regular attachments: #{message.original_regular_attachments.size}"
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.original_body
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.original_regular_attachments.each do |attachment|
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.pec_messages.find { |msg| msg.has_nested_postacerts? }
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: