Generator Public

Code #3833

SMS Notification API Endpoint

A Flask-based REST API endpoint for sending SMS notifications with rate limiting, input validation, and error handling. Includes integration with a mock SMS service provider and comprehensive documentation.

Python
import os
import time
from datetime import datetime, timedelta
from functools import wraps
from flask import Flask, request, jsonify
from flask_cors import CORS
import re

app = Flask(__name__)
CORS(app)

class RateLimiter:
    """
    Rate limiter to prevent API abuse.
    Tracks requests per phone number with a time window.
    """
    def __init__(self, max_requests=5, time_window=3600):
        self.max_requests = max_requests
        self.time_window = time_window
        self.requests = {}
    
    def is_allowed(self, identifier):
        """
        Check if a request is allowed based on rate limit.
        Returns True if request is within limits, False otherwise.
        """
        now = time.time()
        
        if identifier not in self.requests:
            self.requests[identifier] = []
        
        request_times = self.requests[identifier]
        request_times = [req_time for req_time in request_times 
                        if now - req_time < self.time_window]
        
        if len(request_times) < self.max_requests:
            request_times.append(now)
            self.requests[identifier] = request_times
            return True
        
        return False

rate_limiter = RateLimiter(max_requests=5, time_window=3600)

class SMSValidator:
    """
    Validates phone numbers and message content.
    Ensures data integrity before processing.
    """
    
    @staticmethod
    def validate_phone(phone_number):
        """
        Validate phone number format.
        Accepts international format starting with + or standard format.
        """
        pattern = r'^\+?[1-9]\d{1,14}$'
        return re.match(pattern, phone_number.replace(' ', '').replace('-', '')) is not None
    
    @staticmethod
    def validate_message(message):
        """
        Validate message content.
        Message must be between 1 and 160 characters.
        """
        if not message or len(message) == 0:
            return False
        if len(message) > 160:
            return False
        return True
    
    @staticmethod
    def validate_recipient(recipient_email):
        """
        Validate recipient email address.
        Uses basic email pattern validation.
        """
        pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        return re.match(pattern, recipient_email) is not None

class SMSService:
    """
    Mock SMS service provider.
    In production, integrate with real providers like Twilio, AWS SNS, etc.
    """
    
    @staticmethod
    def send_sms(phone_number, message):
        """
        Send SMS to specified phone number.
        Returns success status and delivery ID.
        """
        delivery_id = f'SMS_{int(time.time())}_{hash(phone_number) % 10000}'
        print(f'[SMS Service] Sending to {phone_number}: {message[:50]}...')
        return {
            'success': True,
            'delivery_id': delivery_id,
            'timestamp': datetime.utcnow().isoformat(),
            'phone': phone_number,
            'message_length': len(message)
        }

@app.route('/api/sms/send', methods=['POST'])
def send_sms_endpoint():
    """
    API endpoint to send SMS notification.
    
    Request body:
    {
        'phone_number': '+1234567890' or '1234567890',
        'message': 'Your notification message',
        'sender_id': 'optional_sender_identifier'
    }
    
    Returns JSON response with status and delivery information.
    """
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({
                'success': False,
                'error': 'Request body must be JSON',
                'status_code': 400
            }), 400
        
        phone_number = data.get('phone_number', '').strip()
        message = data.get('message', '').strip()
        sender_id = data.get('sender_id', 'DefaultApp').strip()
        
        if not phone_number:
            return jsonify({
                'success': False,
                'error': 'phone_number is required',
                'status_code': 400
            }), 400
        
        if not message:
            return jsonify({
                'success': False,
                'error': 'message is required',
                'status_code': 400
            }), 400
        
        if not SMSValidator.validate_phone(phone_number):
            return jsonify({
                'success': False,
                'error': 'Invalid phone number format',
                'status_code': 400
            }), 400
        
        if not SMSValidator.validate_message(message):
            return jsonify({
                'success': False,
                'error': 'Message must be between 1 and 160 characters',
                'status_code': 400
            }), 400
        
        if not rate_limiter.is_allowed(phone_number):
            return jsonify({
                'success': False,
                'error': 'Rate limit exceeded. Maximum 5 SMS per hour per number',
                'status_code': 429
            }), 429
        
        result = SMSService.send_sms(phone_number, message)
        
        return jsonify({
            'success': True,
            'message': 'SMS sent successfully',
            'delivery_id': result['delivery_id'],
            'phone_number': phone_number,
            'message_length': result['message_length'],
            'timestamp': result['timestamp'],
            'status_code': 200
        }), 200
    
    except Exception as e:
        print(f'Error in send_sms_endpoint: {str(e)}')
        return jsonify({
            'success': False,
            'error': 'Internal server error',
            'details': str(e),
            'status_code': 500
        }), 500

@app.route('/api/sms/health', methods=['GET'])
def health_check():
    """
    Health check endpoint.
    Verifies API is running and operational.
    """
    return jsonify({
        'status': 'operational',
        'service': 'SMS Notification API',
        'timestamp': datetime.utcnow().isoformat(),
        'version': '1.0.0'
    }), 200

@app.errorhandler(404)
def not_found(error):
    """
    Handle 404 Not Found errors.
    """
    return jsonify({
        'success': False,
        'error': 'Endpoint not found',
        'status_code': 404
    }), 404

@app.errorhandler(405)
def method_not_allowed(error):
    """
    Handle 405 Method Not Allowed errors.
    """
    return jsonify({
        'success': False,
        'error': 'Method not allowed',
        'status_code': 405
    }), 405

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
Prompt: اسکریپت اس ام اس بمبر رایگان