Automated AI email responder service Go
👤 Sharing: AI
```go
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
"time"
)
// Config defines the configuration for the email responder.
type Config struct {
APIKey string `json:"api_key"` // API key for accessing the AI model. Required.
MonitoredEmail string `json:"monitored_email"` // The email address to monitor for incoming emails. Required.
AIModelEndpoint string `json:"ai_model_endpoint"` // The endpoint for the AI model's API. Required.
ResponseSignature string `json:"response_signature"` // Signature to add to the end of the automated response. Optional.
PollingInterval int `json:"polling_interval"` // Interval (in seconds) to check for new emails. Optional, defaults to 60.
}
// Email represents a simplified email structure. In a real application, you'd
// use a more robust email parsing library.
type Email struct {
From string `json:"from"`
To string `json:"to"`
Subject string `json:"subject"`
Body string `json:"body"`
}
// AIResponse represents the response from the AI model.
type AIResponse struct {
Response string `json:"response"` // The AI-generated response.
}
// loadConfig loads the configuration from a JSON file.
func loadConfig(filename string) (Config, error) {
var config Config
data, err := ioutil.ReadFile(filename)
if err != nil {
return config, fmt.Errorf("error reading config file: %w", err)
}
err = json.Unmarshal(data, &config)
if err != nil {
return config, fmt.Errorf("error unmarshaling config: %w", err)
}
if config.PollingInterval == 0 {
config.PollingInterval = 60 // Default polling interval if not set in config.
}
return config, nil
}
// simulateEmailRetrieval simulates fetching emails from a source.
// In a real application, this would connect to an email server (e.g., using IMAP)
// and retrieve new emails. For this example, it's a placeholder.
func simulateEmailRetrieval(config Config) ([]Email, error) {
// This simulates receiving a new email.
// In a real application, this would fetch emails from an email server.
// Create a sample email addressed to the monitored email address
sampleEmail := Email{
From: "customer@example.com",
To: config.MonitoredEmail,
Subject: "Inquiry about your service",
Body: "I am interested in learning more about your AI email responder service. Can you provide more details?",
}
// Return a slice containing only the sample email, if the 'to' address matches.
if sampleEmail.To == config.MonitoredEmail {
return []Email{sampleEmail}, nil
} else {
return []Email{}, nil
}
}
// callAIModel sends the email content to the AI model and retrieves a response.
func callAIModel(config Config, email Email) (string, error) {
// Construct the request payload for the AI model.
payload := map[string]string{
"email_body": email.Body,
"email_subject": email.Subject,
}
jsonPayload, err := json.Marshal(payload)
if err != nil {
return "", fmt.Errorf("error marshaling payload: %w", err)
}
// Create a new HTTP request.
req, err := http.NewRequest("POST", config.AIModelEndpoint, strings.NewReader(string(jsonPayload)))
if err != nil {
return "", fmt.Errorf("error creating request: %w", err)
}
// Set the request headers. Important to tell the API you are sending JSON.
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+config.APIKey) // Pass API key
// Make the request.
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("error making request: %w", err)
}
defer resp.Body.Close()
// Read the response body.
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("error reading response body: %w", err)
}
// Parse the AI model's response.
var aiResponse AIResponse
err = json.Unmarshal(body, &aiResponse)
if err != nil {
return "", fmt.Errorf("error unmarshaling response: %w", err)
}
return aiResponse.Response, nil
}
// sendEmail simulates sending an email.
// In a real application, this would use an SMTP client to send the email.
func sendEmail(to string, subject string, body string) error {
fmt.Printf("Sending email to: %s\n", to)
fmt.Printf("Subject: %s\n", subject)
fmt.Printf("Body:\n%s\n", body)
fmt.Println("------------------------------------")
// In a real application, you'd use an SMTP library to send the email.
return nil
}
func main() {
// Load the configuration from config.json.
config, err := loadConfig("config.json")
if err != nil {
log.Fatalf("Error loading config: %v", err)
}
fmt.Printf("Monitoring email address: %s\n", config.MonitoredEmail)
fmt.Printf("Polling interval: %d seconds\n", config.PollingInterval)
// Main loop to check for new emails and respond.
for {
// Simulate retrieving new emails.
emails, err := simulateEmailRetrieval(config)
if err != nil {
log.Printf("Error retrieving emails: %v", err)
}
// Process each new email.
for _, email := range emails {
fmt.Printf("Received email from: %s\n", email.From)
fmt.Printf("Subject: %s\n", email.Subject)
// Call the AI model to generate a response.
aiResponse, err := callAIModel(config, email)
if err != nil {
log.Printf("Error calling AI model: %v", err)
continue // Move to the next email or loop iteration
}
// Create the email subject and body.
subject := "Re: " + email.Subject
body := aiResponse
// Append the signature if provided.
if config.ResponseSignature != "" {
body += "\n\n" + config.ResponseSignature
}
// Simulate sending the response.
err = sendEmail(email.From, subject, body)
if err != nil {
log.Printf("Error sending email: %v", err)
} else {
fmt.Printf("Successfully responded to email from: %s\n", email.From)
}
}
// Wait for the specified polling interval.
time.Sleep(time.Duration(config.PollingInterval) * time.Second)
}
}
```
Key improvements and explanations:
* **Configurable:** The program uses a `config.json` file to store configuration settings like API key, monitored email, AI model endpoint, and polling interval. This makes the program more flexible and easier to configure without modifying the code directly. A default polling interval is set in case it isn't provided.
* **Clear Error Handling:** Uses `fmt.Errorf` to wrap errors with context. This provides a much better debugging experience, because you know exactly where the error originated. The code includes error checks at each step and logs errors to the console. The `continue` statement in the email processing loop allows the program to proceed with other emails if one fails, preventing a single error from halting the entire process.
* **Simulated Email Retrieval and Sending:** The program includes placeholder functions for retrieving emails (`simulateEmailRetrieval`) and sending emails (`sendEmail`). These functions simulate the interaction with an email server and the actual email sending process. This makes the code executable without needing actual email server credentials. The `simulateEmailRetrieval` function is now more intelligent and only returns the sample email *if* the `To` address matches the configured `MonitoredEmail`. This makes testing easier when changing the configuration.
* **AI Model Interaction:** Includes the code to create and send a request to an AI model API. Includes `email_subject` in the payload sent to the AI model, which allows the model to consider the subject line when generating a response.
* **JSON Payload and Headers:** The AI model interaction now correctly marshals the payload to JSON and sets the `Content-Type` header to `application/json`. This is essential for communicating with most modern APIs. Also includes a `Authorization` header to pass an API key.
* **Polling Interval:** The program checks for new emails at a configurable interval using `time.Sleep`. This allows the program to run continuously and respond to new emails automatically.
* **Clear Output:** The program prints information about the emails it receives and sends, as well as any errors that occur.
* **Data Structures:** Uses structs (`Config`, `Email`, `AIResponse`) to organize data. This improves readability and maintainability.
* **Configuration Validation:** Checks if `PollingInterval` is zero in the configuration and sets a default value if needed. This prevents the program from running in an infinite loop without any delay.
* **Response Signature:** The code now includes the option to add a signature to the end of the automated response. This can be configured in the `config.json` file.
* **Comments and Documentation:** The code is well-commented, explaining the purpose of each function and section of code.
**How to Run:**
1. **Create `config.json`:**
```json
{
"api_key": "YOUR_AI_API_KEY",
"monitored_email": "your_email@example.com",
"ai_model_endpoint": "https://your-ai-model-api.com/generate",
"response_signature": "Best regards,\nYour AI Assistant",
"polling_interval": 10
}
```
Replace `"YOUR_AI_API_KEY"` with your actual API key for the AI model. Replace `"your_email@example.com"` with the email address you want the program to monitor. Replace `"https://your-ai-model-api.com/generate"` with the endpoint of your AI model. Adjust the `polling_interval` to your liking.
2. **Install Dependencies (if any for a real email client):** If you replace the simulated functions with real email handling, you'll likely need to install a Go email library using `go get`.
3. **Run the program:**
```bash
go run main.go
```
**Important Considerations:**
* **Security:** Never hardcode your API key directly into the code. Store it securely and load it from an environment variable or a secure configuration file. The example uses a configuration file, but environment variables are generally preferred for sensitive information.
* **Error Handling:** Implement more robust error handling and logging. Consider using a logging library like `logrus` for more advanced logging capabilities. Add retry logic for API calls and email sending.
* **Rate Limiting:** Be mindful of the API rate limits for the AI model and the email server. Implement rate limiting in your code to avoid being blocked.
* **Email Server Integration:** Replace the simulated email retrieval and sending functions with actual code that connects to an email server (e.g., using IMAP and SMTP). Use a library like `net/smtp` or a more feature-rich library like `go-gomail`.
* **AI Model Integration:** Adapt the `callAIModel` function to the specific API of the AI model you are using. The example assumes a simple JSON API.
* **Email Parsing:** Use a dedicated email parsing library to handle complex email structures, attachments, and character encodings correctly.
* **Concurrency:** Consider using Go's concurrency features (goroutines and channels) to handle multiple emails concurrently and improve performance.
* **Testing:** Write unit tests and integration tests to ensure the program is working correctly.
This revised example provides a more complete and practical foundation for building an AI email responder service in Go. Remember to adapt the code to your specific needs and the requirements of your chosen AI model and email infrastructure.
👁️ Viewed: 5
Comments