CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-otp

A pluggable framework for adding two-factor authentication to Django using one-time passwords.

Pending
Overview
Eval results
Files

email-devices.mddocs/

Email Devices

One-time passwords delivered via email, useful for users who don't have smartphone access to authenticator apps or as a backup authentication method.

Capabilities

EmailDevice Model

class EmailDevice(TimestampMixin, CooldownMixin, ThrottlingMixin, SideChannelDevice):
    """
    Email-based OTP device with cooldown and throttling.
    
    Fields:
    - email: EmailField(blank=True) - Alternative email address
    """
    
    email = models.EmailField(blank=True)
    
    def generate_challenge(self, extra_context=None):
        """
        Generate and email OTP token to user.
        
        Parameters:
        - extra_context: dict - Additional template context
        
        Returns:
        bool - True if challenge was generated and sent
        """
    
    def get_subject(self) -> str:
        """Get email subject line."""
    
    def send_mail(self, body, **kwargs):
        """
        Send email with OTP token.
        
        Parameters:
        - body: str - Email body content
        - **kwargs: Additional email parameters
        """
    
    def get_cooldown_duration(self) -> int:
        """Return cooldown duration from settings."""
    
    def get_throttle_factor(self) -> int:
        """Return throttle factor from settings."""

Admin Interface

class EmailDeviceAdmin(admin.ModelAdmin):
    """Admin interface for EmailDevice."""

Configuration

class OTPEmailSettings(Settings):
    """Email plugin settings with defaults."""

Usage Examples

Creating Email Devices

from django_otp.plugins.otp_email.models import EmailDevice

# Create email device using user's email
device = EmailDevice.objects.create(
    user=user,
    name='Email OTP',
    confirmed=True
)

# Create with alternative email
device = EmailDevice.objects.create(
    user=user,
    name='Backup Email',
    email='backup@example.com',  # Different from user.email
    confirmed=True
)

Generating and Verifying Email Tokens

def send_email_otp(user):
    """Send OTP token via email."""
    
    try:
        device = EmailDevice.objects.get(user=user, confirmed=True)
        
        # Check if generation is allowed (cooldown)
        if device.generate_is_allowed() != True:
            return False, "Please wait before requesting another code"
        
        # Generate and send token
        success = device.generate_challenge()
        return success, "Code sent to email" if success else "Failed to send code"
        
    except EmailDevice.DoesNotExist:
        return False, "No email device configured"

def verify_email_otp(user, token):
    """Verify email OTP token."""
    
    try:
        device = EmailDevice.objects.get(user=user, confirmed=True)
        
        if device.verify_token(token):
            return True, "Token verified successfully"
        else:
            return False, "Invalid or expired token"
            
    except EmailDevice.DoesNotExist:
        return False, "No email device configured"

Configuration Settings

# settings.py

# Email settings
OTP_EMAIL_SENDER = 'noreply@example.com'
OTP_EMAIL_SUBJECT = 'Your verification code'

# Token validity (default: 300 seconds)
OTP_EMAIL_TOKEN_VALIDITY = 600

# Cooldown duration (default: 30 seconds)
OTP_EMAIL_COOLDOWN_DURATION = 60

# Throttling factor (default: 1)
OTP_EMAIL_THROTTLE_FACTOR = 2

# Email templates
OTP_EMAIL_BODY_TEMPLATE = 'Your verification code is: {token}'
OTP_EMAIL_BODY_TEMPLATE_PATH = 'otp/email_body.txt'
OTP_EMAIL_BODY_HTML_TEMPLATE_PATH = 'otp/email_body.html'

Email Templates

Text Template (email_body.txt)

Your verification code is: {{ token }}

This code will expire in {{ valid_minutes }} minutes.

If you did not request this code, please ignore this email.

HTML Template (email_body.html)

<h2>Verification Code</h2>
<p>Your verification code is: <strong>{{ token }}</strong></p>
<p>This code will expire in {{ valid_minutes }} minutes.</p>
<p><small>If you did not request this code, please ignore this email.</small></p>

Install with Tessl CLI

npx tessl i tessl/pypi-django-otp

docs

admin-interface.md

core-authentication.md

device-models.md

django-integration.md

email-devices.md

hotp-devices.md

index.md

oath-algorithms.md

static-tokens.md

totp-devices.md

tile.json