Skip to content

Instantly share code, notes, and snippets.

@davidparys
Created May 29, 2025 18:18
Show Gist options
  • Save davidparys/29a906d9a6047bfe4352873f4e869ac9 to your computer and use it in GitHub Desktop.
Save davidparys/29a906d9a6047bfe4352873f4e869ac9 to your computer and use it in GitHub Desktop.
Create a OVH email profile for iPhone and MacOS (IMAP)
#!/usr/bin/env python3
"""
OVHcloud MX Plan macOS Mail Configuration Generator
This script generates a macOS configuration profile (.mobileconfig) file
that automatically configures OVHcloud MX Plan email settings in the macOS Mail app.
Usage:
python ovh_macos_email_config_generator.py
The script will prompt for email details and generate a .mobileconfig file
that users can install by double-clicking it on their Mac.
"""
import uuid
import sys
import os
import subprocess
import platform
from datetime import datetime
import html
import xml.etree.ElementTree as ET
# Configuration template for macOS
CONFIG_TEMPLATE = '''<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PayloadContent</key>
<array>
<dict>
<key>EmailAccountDescription</key>
<string>{email_description}</string>
<key>EmailAccountName</key>
<string>{display_name}</string>
<key>EmailAccountType</key>
<string>EmailTypeIMAP</string>
<key>EmailAddress</key>
<string>{email_address}</string>
<key>IncomingMailServerAuthentication</key>
<string>EmailAuthPassword</string>
<key>IncomingMailServerHostName</key>
<string>ssl0.ovh.net</string>
<key>IncomingMailServerPortNumber</key>
<integer>993</integer>
<key>IncomingMailServerUseSSL</key>
<true/>
<key>IncomingMailServerUsername</key>
<string>{email_address}</string>
<key>IncomingPassword</key>
<string>{email_password}</string>
<key>OutgoingMailServerAuthentication</key>
<string>EmailAuthPassword</string>
<key>OutgoingMailServerHostName</key>
<string>ssl0.ovh.net</string>
<key>OutgoingMailServerPortNumber</key>
<integer>465</integer>
<key>OutgoingMailServerUseSSL</key>
<true/>
<key>OutgoingMailServerUsername</key>
<string>{email_address}</string>
<key>OutgoingPassword</key>
<string>{email_password}</string>
<key>PayloadDescription</key>
<string>Configures macOS Mail app for OVHcloud MX Plan email account</string>
<key>PayloadDisplayName</key>
<string>{email_description}</string>
<key>PayloadIdentifier</key>
<string>com.ovhcloud.email.macos.{unique_id}</string>
<key>PayloadType</key>
<string>com.apple.mail.managed</string>
<key>PayloadUUID</key>
<string>{payload_uuid}</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</array>
<key>PayloadDescription</key>
<string>This profile configures macOS Mail app to connect to your OVHcloud MX Plan email account</string>
<key>PayloadDisplayName</key>
<string>{email_description}</string>
<key>PayloadIdentifier</key>
<string>com.ovhcloud.email.macos.config.{unique_id}</string>
<key>PayloadOrganization</key>
<string>Mountain Web Studio</string>
<key>PayloadRemovalDisallowed</key>
<false/>
<key>PayloadScope</key>
<string>User</string>
<key>PayloadType</key>
<string>Configuration</string>
<key>PayloadUUID</key>
<string>{root_uuid}</string>
<key>PayloadVersion</key>
<integer>1</integer>
</dict>
</plist>'''
def check_macos():
"""Check if running on macOS"""
if platform.system() != 'Darwin':
print("⚠️ Warning: This script is designed for macOS.")
print(" It will still generate the configuration file, but installation")
print(" instructions are specific to macOS.")
print()
def get_user_input():
"""Collect email configuration details from user"""
print("OVHcloud MX Plan macOS Mail Configuration Generator")
print("=" * 58)
print()
email_address = input("Enter your OVHcloud email address: ").strip()
if not email_address or '@' not in email_address:
print("Error: Please enter a valid email address")
sys.exit(1)
email_password = input("Enter your email password: ").strip()
if not email_password:
print("Error: Password cannot be empty")
sys.exit(1)
display_name = input("Enter display name (e.g., 'John Doe'): ").strip()
if not display_name:
display_name = email_address.split('@')[0].title()
email_description = input(f"Enter account description (default: '{email_address}'): ").strip()
if not email_description:
email_description = email_address
# Validate input lengths to prevent issues
if len(display_name) > 100:
print("Warning: Display name is very long, truncating to 100 characters")
display_name = display_name[:100]
if len(email_description) > 100:
print("Warning: Email description is very long, truncating to 100 characters")
email_description = email_description[:100]
return {
'email_address': email_address,
'email_password': email_password,
'display_name': display_name,
'email_description': email_description
}
def generate_config_file(config_data):
"""Generate the .mobileconfig file for macOS"""
# Generate unique identifiers
unique_id = str(uuid.uuid4()).replace('-', '')[:8]
payload_uuid = str(uuid.uuid4()).upper()
root_uuid = str(uuid.uuid4()).upper()
# Escape XML characters in user input
escaped_data = {
'email_address': escape_xml(config_data['email_address']),
'email_password': escape_xml(config_data['email_password']),
'display_name': escape_xml(config_data['display_name']),
'email_description': escape_xml(config_data['email_description']),
'unique_id': unique_id,
'payload_uuid': payload_uuid,
'root_uuid': root_uuid
}
# Fill template with escaped user data
config_content = CONFIG_TEMPLATE.format(**escaped_data)
# Validate XML before writing
if not validate_xml(config_content):
print("❌ Generated XML is invalid. Please check your input for special characters.")
sys.exit(1)
# Generate filename
safe_email = config_data['email_address'].replace('@', '_at_').replace('.', '_')
filename = f"ovhcloud_macos_email_config_{safe_email}.mobileconfig"
# Write file
try:
with open(filename, 'w', encoding='utf-8') as f:
f.write(config_content)
print(f"\n✅ Configuration profile created successfully!")
print(f"📄 File: {filename}")
print(f"📅 Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
return filename
except Exception as e:
print(f"❌ Error creating configuration file: {e}")
sys.exit(1)
def open_config_file(filename):
"""Attempt to open the configuration file on macOS"""
if platform.system() == 'Darwin':
try:
subprocess.run(['open', filename], check=True)
return True
except subprocess.CalledProcessError:
return False
return False
def print_installation_instructions(filename):
"""Print instructions for installing the configuration profile on macOS and iOS devices"""
print("\n" + "=" * 75)
print("📱 INSTALLATION INSTRUCTIONS")
print("=" * 75)
print()
print("This configuration profile works on both macOS and iPhone/iPad devices.")
print()
# macOS Instructions
print("🖥️ macOS INSTALLATION:")
print("-" * 30)
if platform.system() == 'Darwin':
auto_open = input("Would you like to automatically open the configuration file? (y/N): ").strip().lower()
if auto_open in ['y', 'yes']:
if open_config_file(filename):
print("✅ Configuration file opened automatically!")
print(" Follow the System Preferences prompts to install.")
print()
else:
print("❌ Could not open automatically. Please follow manual steps below.")
print()
print("📋 Manual macOS Installation Steps:")
print("1. Double-click the .mobileconfig file")
print(" OR")
print(" • Open System Preferences/System Settings")
print(" • Go to 'Profiles' (may be under 'Privacy & Security')")
print(" • Click the '+' button and select the .mobileconfig file")
print()
print("2. macOS will show a profile installation dialog:")
print(" • Review the profile details")
print(" • Click 'Install'")
print(" • Enter your Mac password if prompted")
print(" • Click 'Install' again to confirm")
print()
print("3. Open Mail app:")
print(" • Your OVHcloud email account should appear automatically")
print(" • If not, restart the Mail app")
print()
# iPhone/iPad Instructions
print("📱 iPhone/iPad INSTALLATION:")
print("-" * 35)
print()
print("📧 Method 1: Email the profile to yourself")
print("1. Email the .mobileconfig file to your iPhone/iPad")
print("2. Open the email on your iPhone/iPad")
print("3. Tap the .mobileconfig attachment")
print("4. Tap 'Allow' when prompted to download the profile")
print("5. Go to Settings → General → VPN & Device Management")
print("6. Under 'Downloaded Profile', tap the OVHcloud profile")
print("7. Tap 'Install' in the top-right corner")
print("8. Enter your device passcode if prompted")
print("9. Tap 'Install' again to confirm")
print("10. Tap 'Done' when installation is complete")
print()
print("☁️ Method 2: AirDrop (if using macOS)")
print("1. On your Mac, right-click the .mobileconfig file")
print("2. Select 'Share' → 'AirDrop'")
print("3. Select your iPhone/iPad from the AirDrop list")
print("4. On your iPhone/iPad, tap 'Accept'")
print("5. Follow steps 4-10 from Method 1 above")
print()
print("🌐 Method 3: Cloud storage (iCloud, Dropbox, etc.)")
print("1. Upload the .mobileconfig file to your cloud storage")
print("2. On your iPhone/iPad, download the file from the cloud app")
print("3. Tap the downloaded file")
print("4. Follow steps 4-10 from Method 1 above")
print()
print("📧 Alternative: Manual Mail App Setup")
print("If the profile method doesn't work:")
print("1. Open Mail app on your device")
print("2. Go to Settings → Mail → Accounts → Add Account")
print("3. Select 'Other' → 'Add Mail Account'")
print("4. Enter your email details and let Mail auto-configure")
print("5. If auto-config fails, use these manual settings:")
print()
print("📋 Email Settings Summary:")
print(f" • Email: {filename.split('_')[4].replace('_at_', '@').replace('_', '.').replace('.mobileconfig', '')}")
print(f" • IMAP Server: ssl0.ovh.net")
print(f" • IMAP Port: 993 (SSL/TLS)")
print(f" • SMTP Server: ssl0.ovh.net")
print(f" • SMTP Port: 465 (SSL/TLS)")
print(f" • Authentication: Password")
print(f" • Username: Your full email address")
print()
print("⚠️ SECURITY NOTES:")
print(" • The configuration file contains your email password")
print(" • Delete it after installation on all devices")
print(" • Don't share it with others")
print(" • Store passwords securely (Keychain on macOS, iOS Keychain)")
print()
print("🔧 Troubleshooting:")
print(" • Restart Mail app if account doesn't appear")
print(" • On macOS: Check System Preferences → Profiles to verify installation")
print(" • On iPhone/iPad: Check Settings → General → VPN & Device Management")
print(" • Ensure your OVHcloud email account is active")
print(" • Try manual setup if profile installation fails")
print(" • Check device compatibility (iOS 5+, macOS 10.9+ recommended)")
print()
print("❌ If you get 'NSCocoaErrorDomain:3840' error (macOS):")
print(" • This indicates an XML formatting issue")
print(" • Try regenerating the profile with simpler names")
print(" • Avoid special characters in display name and description")
print(" • Contact support if the issue persists")
print()
print("📞 Need Help?")
print(" • Contact OVHcloud support for email account issues")
print(" • Check OVHcloud documentation for additional setup guides")
print(" • Verify your email account is properly configured in OVHcloud panel")
def create_manual_setup_guide(config_data):
"""Create a text file with manual setup instructions for both macOS and iPhone/iPad"""
guide_content = f"""OVHcloud MX Plan Manual Setup Guide for macOS Mail & iPhone/iPad
Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
EMAIL ACCOUNT DETAILS:
Email Address: {config_data['email_address']}
Display Name: {config_data['display_name']}
Description: {config_data['email_description']}
=== macOS MANUAL SETUP STEPS ===
1. Open Mail app on your Mac
2. Go to: Mail → Add Account → Other Mail Account...
3. Enter your details:
- Name: {config_data['display_name']}
- Email Address: {config_data['email_address']}
- Password: [Your email password]
4. Click "Sign In" and wait for auto-configuration
5. If auto-configuration fails, click "Manual Setup" and enter:
INCOMING MAIL SERVER (IMAP):
- Server Name: ssl0.ovh.net
- Port: 993
- Security: SSL/TLS
- Authentication: Password
- Username: {config_data['email_address']}
- Password: [Your email password]
OUTGOING MAIL SERVER (SMTP):
- Server Name: ssl0.ovh.net
- Port: 465
- Security: SSL/TLS
- Authentication: Password
- Username: {config_data['email_address']}
- Password: [Your email password]
6. Click "Done" to complete setup
=== iPhone/iPad MANUAL SETUP STEPS ===
1. Open Settings app on your iPhone/iPad
2. Go to: Mail → Accounts → Add Account
3. Select "Other" → "Add Mail Account"
4. Enter your details:
- Name: {config_data['display_name']}
- Email: {config_data['email_address']}
- Password: [Your email password]
- Description: {config_data['email_description']}
5. Tap "Next" and wait for auto-configuration
6. If auto-configuration fails, select "IMAP" and enter:
INCOMING MAIL SERVER:
- Host Name: ssl0.ovh.net
- User Name: {config_data['email_address']}
- Password: [Your email password]
OUTGOING MAIL SERVER:
- Host Name: ssl0.ovh.net
- User Name: {config_data['email_address']}
- Password: [Your email password]
7. Tap "Next" to verify settings
8. Choose which services to sync (Mail, Contacts, Calendars, Notes)
9. Tap "Save" to complete setup
=== ADVANCED SETTINGS (if needed) ===
If the automatic setup doesn't work, you may need to configure these advanced settings:
IMAP Settings:
- Server: ssl0.ovh.net
- Port: 993
- Security: SSL/TLS
- Authentication: Password
SMTP Settings:
- Server: ssl0.ovh.net
- Port: 465
- Security: SSL/TLS
- Authentication: Password
Alternative SMTP Ports (try if 465 doesn't work):
- Port: 587 with STARTTLS
- Port: 25 (not recommended, less secure)
=== TROUBLESHOOTING ===
macOS:
- Ensure your OVHcloud email account is active
- Check your internet connection
- Verify email address and password are correct
- Try restarting the Mail app
- Check System Preferences → Profiles if using configuration profile
iPhone/iPad:
- Ensure your device has internet connection
- Verify email address and password are correct
- Try restarting the Mail app
- Check Settings → General → VPN & Device Management if using configuration profile
- Make sure iOS is up to date
Common Issues:
- "Cannot verify server identity" - This is normal for some email providers
- "Username or password incorrect" - Double-check your credentials
- "Cannot connect to server" - Check your internet connection and server settings
=== SECURITY NOTES ===
- Always use SSL/TLS encryption when available
- Keep your email password secure and don't share it
- Consider using two-factor authentication if supported by OVHcloud
- Regularly update your device's operating system for security patches
=== CONTACT SUPPORT ===
If you continue to have issues:
- Contact OVHcloud support for email account problems
- Check OVHcloud documentation for additional setup guides
- Verify your email account is properly configured in the OVHcloud control panel
SECURITY REMINDER:
Delete this file after successful setup as it may contain sensitive information.
"""
guide_filename = f"ovhcloud_manual_setup_guide_{config_data['email_address'].replace('@', '_at_').replace('.', '_')}.txt"
try:
with open(guide_filename, 'w', encoding='utf-8') as f:
f.write(guide_content)
return guide_filename
except Exception:
return None
def escape_xml(text):
"""Escape special XML characters in user input"""
if not text:
return ""
# Use html.escape to handle XML special characters
return html.escape(str(text), quote=True)
def validate_xml(xml_content):
"""Validate XML content before writing to file"""
try:
ET.fromstring(xml_content)
return True
except ET.ParseError as e:
print(f"❌ XML validation error: {e}")
return False
def main():
"""Main function"""
try:
# Check if running on macOS
check_macos()
# Get user input
config_data = get_user_input()
# Generate configuration file
filename = generate_config_file(config_data)
# Create manual setup guide
guide_filename = create_manual_setup_guide(config_data)
if guide_filename:
print(f"📋 Manual setup guide: {guide_filename}")
# Print installation instructions
print_installation_instructions(filename)
except KeyboardInterrupt:
print("\n\nOperation cancelled by user.")
sys.exit(0)
except Exception as e:
print(f"\n❌ Unexpected error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment