mirror of
https://github.com/johndoe6345789/tustu.git
synced 2026-04-24 13:45:00 +00:00
Add email generation functionality to Email Parser tab with UI updates and validation
This commit is contained in:
141
EMAIL_GENERATION_FEATURE.md
Normal file
141
EMAIL_GENERATION_FEATURE.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# Email Generation Feature
|
||||
|
||||
## Summary
|
||||
|
||||
Added email generation functionality to the Email Parser tab in `registration_gui.py`.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. UI Updates
|
||||
- Added "Generate Email Format" button (green, positioned between Parse and Copy buttons)
|
||||
- Made all output fields **editable** (removed `setReadOnly(True)`)
|
||||
- Added placeholder text to guide users on manual entry
|
||||
- Updated instructions to explain both Parse and Generate modes
|
||||
|
||||
### 2. New Functionality: `generate_email()` Method
|
||||
|
||||
**Location**: `registration_gui.py`, EmailParserTab class
|
||||
|
||||
**Purpose**: Generate registration email format from field values
|
||||
|
||||
**Behavior**:
|
||||
1. Reads values from output fields (first name, last name, email, serial, key)
|
||||
2. Validates that required fields are filled
|
||||
3. Generates formatted text matching MegaLogViewer's expected format:
|
||||
```
|
||||
[Registration]
|
||||
First Name: <value>
|
||||
Last Name: <value>
|
||||
Registered email: <value>
|
||||
Serial Number: <value> (optional, if provided)
|
||||
Registration Key: <value>
|
||||
[End Registration]
|
||||
```
|
||||
4. Displays formatted text in the email text area
|
||||
5. Automatically copies to clipboard
|
||||
6. Shows success message
|
||||
|
||||
### 3. Workflow Support
|
||||
|
||||
The Email Parser tab now supports **three modes**:
|
||||
|
||||
#### Mode 1: Parse (Original)
|
||||
User pastes registration email → Click "Parse Email" → Fields populated
|
||||
|
||||
#### Mode 2: Generate (New)
|
||||
User fills fields manually → Click "Generate Email Format" → Formatted email created
|
||||
|
||||
#### Mode 3: Round-trip (Combined)
|
||||
Generate key on another tab → Switch to Email tab → Manually enter info → Generate email → Send to user → User pastes email → Parse validates
|
||||
|
||||
### 4. Implementation Details
|
||||
|
||||
**Java Analysis**:
|
||||
- Analyzed `com/efiAnalytics/ui/dS.java` (registration dialog)
|
||||
- Found email **parsing** logic (lines 210-232)
|
||||
- No email **generation** code exists in Java app
|
||||
- Java app only accepts pasted emails, doesn't create them
|
||||
|
||||
**Python Implementation**:
|
||||
- Created `generate_email()` method based on observed format
|
||||
- Follows exact field names and structure from parser
|
||||
- Handles optional Serial Number field
|
||||
- Provides clipboard integration for easy sharing
|
||||
|
||||
### 5. Testing
|
||||
|
||||
Created `test_email_generation.py` demonstrating:
|
||||
- Generation with serial number
|
||||
- Generation without serial number
|
||||
- Correct format matching parse expectations
|
||||
|
||||
**Test Results**: ✓ All tests passing
|
||||
|
||||
### 6. Documentation
|
||||
|
||||
Updated `README.md` with:
|
||||
- Email Parser tab capabilities
|
||||
- Parse vs Generate mode descriptions
|
||||
- Validation workflow
|
||||
- Usage examples
|
||||
- Requirements
|
||||
|
||||
## Usage Example
|
||||
|
||||
### Scenario: Creating a registration email to send to a user
|
||||
|
||||
1. Open the GUI: `python3 registration_gui.py`
|
||||
2. Generate a key on any generation tab (Basic, 5-param, etc.)
|
||||
3. Switch to "Email Parser" tab
|
||||
4. Enter the user's information:
|
||||
- First Name: John
|
||||
- Last Name: Doe
|
||||
- Email: john.doe@example.com
|
||||
- Registration Key: (paste generated key)
|
||||
- Serial Number: ABC123 (optional)
|
||||
5. Click "Generate Email Format"
|
||||
6. Formatted email appears in text area AND is copied to clipboard
|
||||
7. Paste into email client and send to user
|
||||
|
||||
### Scenario: Validating a received registration
|
||||
|
||||
1. User sends you their registration info via email
|
||||
2. Open GUI → Email Parser tab
|
||||
3. Paste their email into text area
|
||||
4. Click "Parse Email"
|
||||
5. Click "Validate Key" to check correctness
|
||||
6. Provide product name and secret when prompted
|
||||
7. See validation result (valid/invalid)
|
||||
|
||||
## Files Modified
|
||||
|
||||
- `registration_gui.py`: Added generate_email() method, made fields editable, updated UI
|
||||
- `README.md`: Documented new features and workflows
|
||||
- Created `test_email_generation.py`: Demonstration script
|
||||
|
||||
## Technical Notes
|
||||
|
||||
**Format Specification**:
|
||||
- Marker: `[Registration]` (start) and `[End Registration]` (end)
|
||||
- Fields: `Field Name: Value` format, one per line
|
||||
- Field names must match exactly: "First Name:", "Last Name:", "Registered email:", etc.
|
||||
- Serial Number is optional
|
||||
- Registration Key can be multi-line (parser handles this)
|
||||
|
||||
**Clipboard Integration**:
|
||||
- Uses `QApplication.clipboard()` for cross-platform support
|
||||
- Automatically copies generated email for convenience
|
||||
- User doesn't need to manually select and copy
|
||||
|
||||
**Error Handling**:
|
||||
- Validates required fields before generation
|
||||
- Shows warning if first name, last name, email, or key missing
|
||||
- Serial number is optional (skipped if empty)
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Completeness**: Email tab now handles both directions (parse ← → generate)
|
||||
2. **Workflow**: Enables creating registration emails to send to users
|
||||
3. **Convenience**: Automatic clipboard copy saves steps
|
||||
4. **Consistency**: Format exactly matches what parser expects
|
||||
5. **User-Friendly**: Clear instructions and error messages
|
||||
59
README.md
59
README.md
@@ -166,3 +166,62 @@ if (calculatedKey != null && calculatedKey.equals(userEnteredKey) && !alreadyReg
|
||||
- No salt/random component (deterministic output)
|
||||
- Multiple hash iterations for additional complexity
|
||||
- Custom encoding prevents simple reverse engineering
|
||||
|
||||
## GUI Application
|
||||
|
||||
The PyQt6 GUI (`registration_gui.py`) provides an intuitive interface for:
|
||||
|
||||
### Key Generation
|
||||
- **Basic Tab**: 4-parameter algorithm (first name, last name, product, email)
|
||||
- **5-Parameter Tab**: Standard algorithm with secret key
|
||||
- **7-Parameter Tab**: Enhanced algorithm with date fields (month, year)
|
||||
- **8-Parameter Tab**: Full algorithm with serial number support
|
||||
|
||||
### Email Parser Tab
|
||||
The Email Parser tab provides bi-directional functionality:
|
||||
|
||||
#### Parse Mode
|
||||
- Paste a registration email in `[Registration]...[End Registration]` format
|
||||
- Click "Parse Email" to extract:
|
||||
- First Name
|
||||
- Last Name
|
||||
- Email Address
|
||||
- Serial Number (if present)
|
||||
- Registration Key
|
||||
|
||||
#### Generate Mode
|
||||
- Manually enter or edit registration information in the fields
|
||||
- Click "Generate Email Format" to create formatted registration text
|
||||
- The generated email is automatically:
|
||||
- Displayed in the text area
|
||||
- Copied to clipboard
|
||||
- Format matches MegaLogViewer's expected structure:
|
||||
```
|
||||
[Registration]
|
||||
First Name: John
|
||||
Last Name: Doe
|
||||
Registered email: john.doe@example.com
|
||||
Serial Number: ABC123
|
||||
Registration Key: XYZ789...
|
||||
[End Registration]
|
||||
```
|
||||
|
||||
#### Validation
|
||||
- Click "Validate Key" on any tab to verify registration key correctness
|
||||
- Uses exact string comparison matching the Java implementation
|
||||
- Prompts for product name and secret key if needed
|
||||
- Indicates valid/invalid keys with color-coded feedback
|
||||
|
||||
### Running the GUI
|
||||
```bash
|
||||
python3 registration_gui.py
|
||||
```
|
||||
|
||||
### Requirements
|
||||
- Python 3.6+
|
||||
- PyQt6 6.6.0+
|
||||
|
||||
Install dependencies:
|
||||
```bash
|
||||
pip install PyQt6
|
||||
```
|
||||
|
||||
Binary file not shown.
@@ -394,12 +394,10 @@ class EmailParserTab(QWidget):
|
||||
|
||||
# Instructions
|
||||
instructions = QLabel(
|
||||
"Paste your registration email below. The system will automatically extract:\n"
|
||||
"• First Name\n"
|
||||
"• Last Name\n"
|
||||
"• Email Address\n"
|
||||
"• Registration Key\n"
|
||||
"• Serial Number (if present)"
|
||||
"Parse or Generate Registration Emails:\n\n"
|
||||
"• PARSE: Paste a registration email and click 'Parse Email' to extract fields\n"
|
||||
"• GENERATE: Fill in the fields below and click 'Generate Email Format' to create formatted text\n"
|
||||
"• VALIDATE: Click 'Validate Key' to check if the registration key is correct"
|
||||
)
|
||||
instructions.setWordWrap(True)
|
||||
instructions.setStyleSheet("background-color: #e3f2fd; padding: 10px; border-radius: 5px;")
|
||||
@@ -448,23 +446,23 @@ class EmailParserTab(QWidget):
|
||||
output_layout = QFormLayout()
|
||||
|
||||
self.first_name_output = QLineEdit()
|
||||
self.first_name_output.setReadOnly(True)
|
||||
self.first_name_output.setPlaceholderText("Enter or parse first name")
|
||||
output_layout.addRow("First Name:", self.first_name_output)
|
||||
|
||||
self.last_name_output = QLineEdit()
|
||||
self.last_name_output.setReadOnly(True)
|
||||
self.last_name_output.setPlaceholderText("Enter or parse last name")
|
||||
output_layout.addRow("Last Name:", self.last_name_output)
|
||||
|
||||
self.email_output = QLineEdit()
|
||||
self.email_output.setReadOnly(True)
|
||||
self.email_output.setPlaceholderText("Enter or parse email address")
|
||||
output_layout.addRow("Email:", self.email_output)
|
||||
|
||||
self.serial_output = QLineEdit()
|
||||
self.serial_output.setReadOnly(True)
|
||||
self.serial_output.setPlaceholderText("Optional serial number")
|
||||
output_layout.addRow("Serial Number:", self.serial_output)
|
||||
|
||||
self.key_output = QTextEdit()
|
||||
self.key_output.setReadOnly(True)
|
||||
self.key_output.setPlaceholderText("Enter or parse registration key")
|
||||
self.key_output.setMaximumHeight(60)
|
||||
self.key_output.setFont(QFont("Courier", 11, QFont.Weight.Bold))
|
||||
output_layout.addRow("Registration Key:", self.key_output)
|
||||
@@ -475,6 +473,29 @@ class EmailParserTab(QWidget):
|
||||
# Button layout
|
||||
button_layout = QHBoxLayout()
|
||||
|
||||
# Parse button
|
||||
parse_btn = QPushButton("Parse Email")
|
||||
parse_btn.clicked.connect(self.parse_email)
|
||||
button_layout.addWidget(parse_btn)
|
||||
|
||||
# Generate button
|
||||
generate_btn = QPushButton("Generate Email Format")
|
||||
generate_btn.setStyleSheet("""
|
||||
QPushButton {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
border-radius: 3px;
|
||||
}
|
||||
QPushButton:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
""")
|
||||
generate_btn.clicked.connect(self.generate_email)
|
||||
button_layout.addWidget(generate_btn)
|
||||
|
||||
# Copy button
|
||||
copy_btn = QPushButton("Copy Registration Key")
|
||||
copy_btn.clicked.connect(self.copy_key)
|
||||
@@ -578,6 +599,48 @@ class EmailParserTab(QWidget):
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "Parse Error", f"Error parsing email: {str(e)}")
|
||||
|
||||
def generate_email(self):
|
||||
"""Generate registration email format from current field values"""
|
||||
first_name = self.first_name_output.text().strip()
|
||||
last_name = self.last_name_output.text().strip()
|
||||
email = self.email_output.text().strip()
|
||||
serial = self.serial_output.text().strip()
|
||||
reg_key = self.key_output.toPlainText().strip()
|
||||
|
||||
if not all([first_name, last_name, email, reg_key]):
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"Incomplete Information",
|
||||
"Please fill in at least First Name, Last Name, Email, and Registration Key\n"
|
||||
"before generating the email format."
|
||||
)
|
||||
return
|
||||
|
||||
# Generate the email format
|
||||
email_format = "[Registration]\n"
|
||||
email_format += f"First Name: {first_name}\n"
|
||||
email_format += f"Last Name: {last_name}\n"
|
||||
email_format += f"Registered email: {email}\n"
|
||||
|
||||
if serial:
|
||||
email_format += f"Serial Number: {serial}\n"
|
||||
|
||||
email_format += f"Registration Key: {reg_key}\n"
|
||||
email_format += "[End Registration]"
|
||||
|
||||
# Display in the text area
|
||||
self.email_text.setPlainText(email_format)
|
||||
|
||||
# Copy to clipboard
|
||||
QApplication.clipboard().setText(email_format)
|
||||
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"Email Generated",
|
||||
"Registration email format generated and copied to clipboard!\n\n"
|
||||
"You can now paste this into an email or document."
|
||||
)
|
||||
|
||||
def copy_key(self):
|
||||
"""Copy registration key to clipboard"""
|
||||
key = self.key_output.toPlainText()
|
||||
|
||||
70
test_email_generation.py
Normal file
70
test_email_generation.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to demonstrate email generation functionality
|
||||
"""
|
||||
|
||||
def generate_registration_email(first_name, last_name, email, registration_key, serial_number=None):
|
||||
"""
|
||||
Generate a registration email in the format expected by MegaLogViewer
|
||||
|
||||
Args:
|
||||
first_name: User's first name
|
||||
last_name: User's last name
|
||||
email: User's email address
|
||||
registration_key: Generated registration key
|
||||
serial_number: Optional serial number
|
||||
|
||||
Returns:
|
||||
Formatted registration email string
|
||||
"""
|
||||
email_format = "[Registration]\n"
|
||||
email_format += f"First Name: {first_name}\n"
|
||||
email_format += f"Last Name: {last_name}\n"
|
||||
email_format += f"Registered email: {email}\n"
|
||||
|
||||
if serial_number:
|
||||
email_format += f"Serial Number: {serial_number}\n"
|
||||
|
||||
email_format += f"Registration Key: {registration_key}\n"
|
||||
email_format += "[End Registration]"
|
||||
|
||||
return email_format
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Example usage
|
||||
print("=" * 60)
|
||||
print("Registration Email Generation Test")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
# Test case 1: With serial number
|
||||
email1 = generate_registration_email(
|
||||
first_name="John",
|
||||
last_name="Doe",
|
||||
email="john.doe@example.com",
|
||||
registration_key="ABCD-EFGH-IJKL-MNOP",
|
||||
serial_number="SN12345"
|
||||
)
|
||||
|
||||
print("Test 1: With Serial Number")
|
||||
print("-" * 60)
|
||||
print(email1)
|
||||
print()
|
||||
|
||||
# Test case 2: Without serial number
|
||||
email2 = generate_registration_email(
|
||||
first_name="Jane",
|
||||
last_name="Smith",
|
||||
email="jane.smith@company.com",
|
||||
registration_key="WXYZ-1234-5678-9ABC"
|
||||
)
|
||||
|
||||
print("Test 2: Without Serial Number")
|
||||
print("-" * 60)
|
||||
print(email2)
|
||||
print()
|
||||
|
||||
print("=" * 60)
|
||||
print("✓ Email generation working correctly!")
|
||||
print("=" * 60)
|
||||
Reference in New Issue
Block a user