From f8684077a23688abf9f552bc2dcb1c01af4430b0 Mon Sep 17 00:00:00 2001 From: Rune Olsen Date: Mon, 26 Jan 2026 12:55:56 +0100 Subject: [PATCH] email testing --- .env.example | 4 +- MODELS.md | 161 +++++++++++++++++++++++++++++++++++++++ README.md | 23 +++++- SMTP_CONFIG.md | 16 +++- config.yaml | 14 ++-- src/test_email_simple.py | 109 ++++++++++++++++++++++++++ test_email.py | 132 ++++++++++++++++++++++++++++++++ 7 files changed, 447 insertions(+), 12 deletions(-) create mode 100644 MODELS.md create mode 100644 src/test_email_simple.py create mode 100644 test_email.py diff --git a/.env.example b/.env.example index f6ec9ad..5a90091 100644 --- a/.env.example +++ b/.env.example @@ -1,11 +1,13 @@ # OpenRouter API Configuration -OPENROUTER_API_KEY=your_api_key_here +# No quotes needed - just paste your key directly +OPENROUTER_API_KEY=sk-or-v1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx # Optional: Your site info for OpenRouter rankings OPENROUTER_SITE_URL=https://your-site.com OPENROUTER_SITE_NAME=YourSiteName # SMTP Credentials for your mail server +# No quotes needed - even if your password contains special characters SMTP_USERNAME=your-email@yourdomain.com SMTP_PASSWORD=your-smtp-password diff --git a/MODELS.md b/MODELS.md new file mode 100644 index 0000000..62fcc69 --- /dev/null +++ b/MODELS.md @@ -0,0 +1,161 @@ +# OpenRouter Model Reference + +Quick reference for choosing the right AI model for News Agent. + +## Recommended Models + +### Best Overall: `google/gemini-flash-1.5-8b` +- **Cost:** ~$0.05-0.15/day +- **Quality:** Excellent +- **Speed:** Very fast +- **Best for:** Production use, daily digests + +### Best Free: `google/gemini-2.0-flash-exp:free` +- **Cost:** FREE +- **Quality:** Good (experimental) +- **Speed:** Fast +- **Best for:** Testing, low-budget setups +- **Note:** Experimental, may change + +### Budget Option: `meta-llama/llama-3.1-8b-instruct:free` +- **Cost:** FREE +- **Quality:** Decent +- **Speed:** Moderate +- **Best for:** Testing, development + +### High Quality: `anthropic/claude-3.5-haiku` +- **Cost:** ~$0.10-0.25/day +- **Quality:** Excellent +- **Speed:** Fast +- **Best for:** When quality matters most + +### OpenAI Option: `openai/gpt-4o-mini` +- **Cost:** ~$0.08-0.20/day +- **Quality:** Very good +- **Speed:** Fast +- **Best for:** Balanced quality/cost + +## How to Change Model + +Edit `config.yaml`: + +```yaml +ai: + model: "google/gemini-flash-1.5-8b" # Change this line +``` + +## Full Model List + +See all available models at: https://openrouter.ai/models + +Filter by: +- **Free models** - Search for `:free` suffix +- **Context length** - Important for long articles +- **Supported features** - JSON mode, function calling, etc. + +## Cost Comparison (Daily Estimates) + +Based on processing ~50 articles/day with 15 summaries: + +| Model | Daily Cost | Monthly Cost | Quality | +|-------|-----------|--------------|---------| +| `google/gemini-2.0-flash-exp:free` | $0.00 | $0.00 | Good | +| `meta-llama/llama-3.1-8b-instruct:free` | $0.00 | $0.00 | Decent | +| `google/gemini-flash-1.5-8b` | $0.05-0.15 | $1.50-4.50 | Excellent | +| `openai/gpt-4o-mini` | $0.08-0.20 | $2.40-6.00 | Very Good | +| `anthropic/claude-3.5-haiku` | $0.10-0.25 | $3.00-7.50 | Excellent | +| `openai/gpt-4o` | $0.50-1.50 | $15-45 | Outstanding | + +*Costs vary based on article length and quantity* + +## Testing a New Model + +1. Update `config.yaml`: + ```yaml + ai: + model: "new-model-name" + ``` + +2. Run a test: + ```bash + source .venv/bin/activate + python -m src.main + ``` + +3. Check quality of summaries in the email + +4. Monitor costs at: https://openrouter.ai/activity + +## Model Selection Tips + +### Choose FREE models if: +- You're testing the system +- Cost is a major concern +- Article quality/accuracy is less critical + +### Choose PAID models if: +- You want best quality summaries +- You need reliable daily digests +- You value accurate relevance scoring + +### Performance vs Cost: +- **Gemini Flash 1.5-8b** - Best balance +- **Claude Haiku** - Best quality for cost +- **GPT-4o-mini** - Good all-rounder +- **Free models** - Testing/development + +## Troubleshooting + +### Error: "No endpoints found for [model]" + +The model name is incorrect or not available on OpenRouter. + +**Solution:** +1. Check model name at: https://openrouter.ai/models +2. Copy exact model ID (e.g., `google/gemini-flash-1.5-8b`) +3. Update `config.yaml` +4. Restart the service + +### Model Seems Slow + +Some models are slower than others. + +**Solutions:** +- Try `google/gemini-flash-1.5-8b` (fastest) +- Reduce `max_articles` in config (process fewer articles) +- Use cheaper/faster models for filtering, premium for summarization + +### Poor Summary Quality + +The model might not be good at summarization. + +**Solutions:** +- Try `anthropic/claude-3.5-haiku` (excellent summarization) +- Adjust prompts in `src/ai/prompts.py` +- Increase temperature for more creative summaries +- Try different models + +### High Costs + +You're using an expensive model or processing too many articles. + +**Solutions:** +1. Switch to cheaper model (Gemini Flash or free options) +2. Increase `min_score` to filter more aggressively +3. Reduce `max_articles` limit +4. Monitor usage: https://openrouter.ai/activity + +## Advanced: Using Different Models for Different Tasks + +You could modify the code to use: +- **Fast/cheap model** for filtering (scoring articles) +- **High-quality model** for summarization + +Edit `src/main.py` to instantiate different clients for different tasks. + +## Need Help? + +- **Model pricing:** https://openrouter.ai/models (click model for details) +- **API docs:** https://openrouter.ai/docs +- **Check costs:** https://openrouter.ai/activity +- **Model comparison:** Test different models and compare results diff --git a/README.md b/README.md index 508ab2c..78ffa0f 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ email: - **SendGrid**: `smtp.sendgrid.net:587`, use API key as password Optionally adjust: -- AI model (default: `google/gemini-flash-1.5` - fast and cheap) +- AI model (default: `google/gemini-flash-1.5-8b` - fast and cheap) - Filtering threshold (default: 6.5/10) - Max articles per digest (default: 15) - RSS sources (add/remove feeds) @@ -204,11 +204,15 @@ sources: ### AI Configuration **Models** (from cheap to expensive): -- `google/gemini-flash-1.5` - Fast, cheap, good quality (recommended) -- `meta-llama/llama-3.1-8b-instruct` - Very cheap +- `google/gemini-flash-1.5-8b` - Fast, cheap, good quality (recommended) +- `google/gemini-2.0-flash-exp:free` - Free, experimental (good for testing) +- `meta-llama/llama-3.1-8b-instruct:free` - Free, decent quality - `anthropic/claude-3.5-haiku` - Better quality, slightly more expensive - `openai/gpt-4o-mini` - Good quality, moderate price +See **[MODELS.md](MODELS.md)** for detailed comparison and selection guide. +Full list at: https://openrouter.ai/models + **Filtering:** ```yaml ai: @@ -263,9 +267,16 @@ systemctl --user restart news-agent.timer ### API Errors +**Error: "No endpoints found for [model]"** +- The model name is incorrect +- Check correct model names in `MODELS.md` +- Update `config.yaml` with correct model ID + +**Other API errors:** 1. **Verify API key in `.env`** 2. **Check OpenRouter credit balance:** https://openrouter.ai/credits 3. **Check rate limits in logs** +4. **Try a different model** (see `MODELS.md`) ### Service Not Running @@ -290,12 +301,16 @@ python -m src.main ## Cost Estimation -Using `google/gemini-flash-1.5` (recommended): +Using `google/gemini-flash-1.5-8b` (recommended): - **Daily:** ~$0.05-0.15 (varies by article count) - **Monthly:** ~$1.50-4.50 - **Yearly:** ~$18-54 +**Free Options:** +- `google/gemini-2.0-flash-exp:free` - Completely free (experimental) +- `meta-llama/llama-3.1-8b-instruct:free` - Completely free + Factors affecting cost: - Number of new articles - Content length diff --git a/SMTP_CONFIG.md b/SMTP_CONFIG.md index b3aa195..30e7e2c 100644 --- a/SMTP_CONFIG.md +++ b/SMTP_CONFIG.md @@ -23,7 +23,21 @@ SMTP_USERNAME=your-email@yourdomain.com SMTP_PASSWORD=your-password-or-app-password ``` -**Security Note:** The `.env` file is gitignored and should never be committed to version control. +**Important Notes:** +- **NO quotes needed** - Values should be plain text without quotes +- **Special characters are OK** - Passwords with `!@#$%` etc. work fine +- **Security:** The `.env` file is gitignored and should never be committed to version control + +**Examples:** +```env +# Correct - no quotes +SMTP_USERNAME=admin@example.com +SMTP_PASSWORD=P@ssw0rd!123 + +# Wrong - don't use quotes +SMTP_USERNAME="admin@example.com" # ❌ +SMTP_PASSWORD='P@ssw0rd!123' # ❌ +``` ### 2. Edit `config.yaml` diff --git a/config.yaml b/config.yaml index 0fcc02a..6cba7a0 100644 --- a/config.yaml +++ b/config.yaml @@ -61,9 +61,9 @@ sources: url: "https://www.engadget.com/rss.xml" category: "gadgets" - - name: "AnandTech" - url: "https://www.anandtech.com/rss/" - category: "gadgets" + #- name: "AnandTech" + # url: "https://www.anandtech.com/rss/" + # category: "gadgets" - name: "Tom's Hardware" url: "https://www.tomshardware.com/feeds/all" @@ -72,10 +72,12 @@ sources: ai: provider: "openrouter" base_url: "https://openrouter.ai/api/v1" - model: "google/gemini-flash-1.5" - # Alternative models: + model: "google/gemini-flash-1.5-8b" + # Alternative models (see https://openrouter.ai/models for full list): + # - "google/gemini-2.0-flash-exp:free" (free, experimental) # - "anthropic/claude-3.5-haiku" (better quality, slightly more expensive) - # - "meta-llama/llama-3.1-8b-instruct" (very cheap) + # - "meta-llama/llama-3.1-8b-instruct:free" (free, good quality) + # - "openai/gpt-4o-mini" (good quality, moderate price) filtering: enabled: true diff --git a/src/test_email_simple.py b/src/test_email_simple.py new file mode 100644 index 0000000..0e968f9 --- /dev/null +++ b/src/test_email_simple.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +"""Simple email test - run with: python -m src.test_email_simple""" + +from datetime import datetime +from .config import get_config +from .logger import setup_logger +from .email.sender import EmailSender + + +def main(): + """Send a test email""" + setup_logger() + config = get_config() + + print("\n" + "=" * 60) + print("Testing Email Configuration") + print("=" * 60) + + print(f"\nSMTP Server: {config.email.smtp.host}:{config.email.smtp.port}") + print(f"TLS: {config.email.smtp.use_tls}") + print(f"SSL: {config.email.smtp.use_ssl}") + print(f"From: {config.email.from_}") + print(f"To: {config.email.to}") + print(f"Username: {config.env.smtp_username or '(not set)'}") + print(f"Password: {'***' if config.env.smtp_password else '(not set)'}") + + print("\nSending test email...") + + # Create test email content + subject = "News Agent Test Email" + + html_content = f""" + + + + + + +
+

✓ News Agent Email Test

+
+
+

Congratulations! Your email configuration is working correctly.

+ +

Test Details:

+ + +

Your News Agent is now ready to send daily digests!

+ +
+

+ This is a test email from News Agent. If you received this, + your SMTP configuration is correct and you should start receiving + daily news digests. +

+
+ + + """ + + text_content = f""" +News Agent Email Test +===================== + +✓ Congratulations! Your email configuration is working correctly. + +Test Details: +- Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} +- SMTP Server: {config.email.smtp.host}:{config.email.smtp.port} +- Encryption: {"TLS" if config.email.smtp.use_tls else "SSL" if config.email.smtp.use_ssl else "None"} + +Your News Agent is now ready to send daily digests! + +--- +This is a test email from News Agent. If you received this, +your SMTP configuration is correct and you should start receiving +daily news digests. + """ + + # Send email + sender = EmailSender() + success = sender.send(subject, html_content, text_content) + + print("\n" + "=" * 60) + if success: + print("✓ SUCCESS! Test email sent successfully!") + print(f"✓ Check your inbox: {config.email.to}") + else: + print("✗ FAILED! Email could not be sent.") + print("✗ Check the error messages above.") + print("\nTroubleshooting steps:") + print("1. Verify SMTP credentials in .env file") + print("2. Check SMTP server settings in config.yaml") + print("3. Review logs: cat data/logs/news-agent.log") + print("4. See SMTP_CONFIG.md for detailed troubleshooting") + print("=" * 60 + "\n") + + +if __name__ == "__main__": + main() diff --git a/test_email.py b/test_email.py new file mode 100644 index 0000000..bc00678 --- /dev/null +++ b/test_email.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +"""Quick email sending test script""" + +import sys +from datetime import datetime + +# Add src to path +sys.path.insert(0, "src") + +from src.config import get_config +from src.logger import setup_logger +from src.email.sender import EmailSender + + +def test_email(): + """Send a test email""" + setup_logger() + config = get_config() + + print("\n" + "=" * 60) + print("Testing Email Configuration") + print("=" * 60) + + print(f"\nSMTP Server: {config.email.smtp.host}:{config.email.smtp.port}") + print(f"TLS: {config.email.smtp.use_tls}") + print(f"SSL: {config.email.smtp.use_ssl}") + print(f"From: {config.email.from_}") + print(f"To: {config.email.to}") + print(f"Username: {config.env.smtp_username or '(not set)'}") + print(f"Password: {'***' if config.env.smtp_password else '(not set)'}") + + print("\nSending test email...") + + # Create test email content + subject = "News Agent Test Email" + + html_content = ( + """ + + + + + + +
+

✓ News Agent Email Test

+
+
+

Congratulations! Your email configuration is working correctly.

+ +

Test Details:

+ + +

Your News Agent is now ready to send daily digests!

+ +
+

+ This is a test email from News Agent. If you received this, + your SMTP configuration is correct and you should start receiving + daily news digests. +

+
+ + + """ + ) + + text_content = f""" +News Agent Email Test +===================== + +✓ Congratulations! Your email configuration is working correctly. + +Test Details: +- Date: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} +- SMTP Server: {config.email.smtp.host}:{config.email.smtp.port} +- Encryption: {"TLS" if config.email.smtp.use_tls else "SSL" if config.email.smtp.use_ssl else "None"} + +Your News Agent is now ready to send daily digests! + +--- +This is a test email from News Agent. If you received this, +your SMTP configuration is correct and you should start receiving +daily news digests. + """ + + # Send email + sender = EmailSender() + success = sender.send(subject, html_content, text_content) + + print("\n" + "=" * 60) + if success: + print("✓ SUCCESS! Test email sent successfully!") + print(f"✓ Check your inbox: {config.email.to}") + else: + print("✗ FAILED! Email could not be sent.") + print("✗ Check the error messages above.") + print("\nTroubleshooting steps:") + print("1. Verify SMTP credentials in .env file") + print("2. Check SMTP server settings in config.yaml") + print("3. Review logs: cat data/logs/news-agent.log") + print("4. See SMTP_CONFIG.md for detailed troubleshooting") + print("=" * 60 + "\n") + + return success + + +if __name__ == "__main__": + try: + success = test_email() + sys.exit(0 if success else 1) + except Exception as e: + print(f"\n✗ ERROR: {e}") + import traceback + + traceback.print_exc() + sys.exit(1)