Signals

Django FTP Server provides Django signals that are emitted when various FTP events occur. This allows you to hook into FTP server events for logging, auditing, or custom processing.

Available Signals

All signals are defined in django_ftpserver.signals.

Connection Signals

ftp_server_started

Sent when the FTP server starts.

Arguments:
  • sender: The command class

  • server: The FTPServer instance

  • host: Server host address

  • port: Server port number

ftp_server_stopped

Sent when the FTP server stops.

Arguments:
  • sender: The command class

  • server: The FTPServer instance

  • host: Server host address

  • port: Server port number

ftp_client_connected

Sent when a client connects to the server.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • remote_ip: Client IP address

  • remote_port: Client port number

ftp_client_disconnected

Sent when a client disconnects from the server.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username (if authenticated, otherwise None)

  • remote_ip: Client IP address

Authentication Signals

ftp_login

Sent when a user successfully logs in.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • remote_ip: Client IP address

ftp_login_failed

Sent when a login attempt fails.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Attempted username

  • remote_ip: Client IP address

ftp_logout

Sent when a user logs out.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • remote_ip: Client IP address

File Transfer Signals

ftp_file_received

Sent when a file upload completes successfully.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • path: File path

  • remote_ip: Client IP address

ftp_file_sent

Sent when a file download completes successfully.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • path: File path

  • remote_ip: Client IP address

ftp_file_received_incomplete

Sent when a file upload is interrupted.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • path: File path

  • remote_ip: Client IP address

ftp_file_sent_incomplete

Sent when a file download is interrupted.

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • path: File path

  • remote_ip: Client IP address

File Operation Signals

ftp_file_deleted

Sent when a file is deleted (DELE command).

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • path: Deleted file path

  • remote_ip: Client IP address

ftp_file_renamed

Sent when a file or directory is renamed (RNFR/RNTO commands).

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • path_from: Original path

  • path_to: New path

  • remote_ip: Client IP address

ftp_directory_created

Sent when a directory is created (MKD command).

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • path: Created directory path

  • remote_ip: Client IP address

ftp_directory_deleted

Sent when a directory is deleted (RMD command).

Arguments:
  • sender: The handler class

  • handler: The FTPHandler instance

  • username: Username

  • path: Deleted directory path

  • remote_ip: Client IP address

Usage Examples

Basic Signal Receiver

Create a file receivers.py in your Django app:

import logging
from django.dispatch import receiver
from django_ftpserver.signals import ftp_login, ftp_logout, ftp_login_failed

logger = logging.getLogger('ftp.access')

@receiver(ftp_login)
def log_ftp_login(sender, username, remote_ip, **kwargs):
    logger.info("FTP login: user=%s, ip=%s", username, remote_ip)

@receiver(ftp_logout)
def log_ftp_logout(sender, username, remote_ip, **kwargs):
    logger.info("FTP logout: user=%s, ip=%s", username, remote_ip)

@receiver(ftp_login_failed)
def log_ftp_login_failed(sender, username, remote_ip, **kwargs):
    logger.warning("FTP login failed: user=%s, ip=%s", username, remote_ip)

Make sure to import your receivers in your app’s apps.py:

from django.apps import AppConfig

class MyAppConfig(AppConfig):
    name = 'myapp'

    def ready(self):
        import myapp.receivers  # noqa

File Upload Processing

Process uploaded files (e.g., virus scanning, thumbnail generation):

from django.dispatch import receiver
from django_ftpserver.signals import ftp_file_received

@receiver(ftp_file_received)
def process_uploaded_file(sender, username, path, **kwargs):
    # Queue async task for heavy processing
    from myapp.tasks import process_file
    process_file.delay(path, username)

Audit Logging

Store FTP events in a database for auditing:

from django.dispatch import receiver
from django_ftpserver.signals import (
    ftp_login, ftp_logout,
    ftp_file_received, ftp_file_sent, ftp_file_deleted
)
from myapp.models import FTPAuditLog

@receiver(ftp_login)
def audit_login(sender, username, remote_ip, **kwargs):
    FTPAuditLog.objects.create(
        event_type='login',
        username=username,
        remote_ip=remote_ip,
    )

@receiver(ftp_file_received)
def audit_upload(sender, username, path, remote_ip, **kwargs):
    FTPAuditLog.objects.create(
        event_type='upload',
        username=username,
        remote_ip=remote_ip,
        path=path,
    )

@receiver(ftp_file_deleted)
def audit_delete(sender, username, path, remote_ip, **kwargs):
    FTPAuditLog.objects.create(
        event_type='delete',
        username=username,
        remote_ip=remote_ip,
        path=path,
    )

Debug Logging

The FTP handlers emit DEBUG level logs for all events. You can enable these logs in your Django settings:

LOGGING = {
    'version': 1,
    'handlers': {
        'console': {'class': 'logging.StreamHandler'},
    },
    'loggers': {
        'django_ftpserver.handlers': {
            'handlers': ['console'],
            'level': 'DEBUG',
        },
    },
}

To disable the debug logs, set the level to INFO or higher:

LOGGING = {
    'version': 1,
    'loggers': {
        'django_ftpserver.handlers': {
            'level': 'INFO',
        },
    },
}

Handler Classes

To use signals, make sure you are using the Django FTP handlers. By default, the management command uses these handlers automatically.

Available handlers:

  • django_ftpserver.handlers.DjangoFTPHandler - FTP handler with signal support

  • django_ftpserver.handlers.DjangoTLS_FTPHandler - TLS FTP handler with signal support (requires pyOpenSSL)

You can also specify custom handlers in your Django settings:

FTPSERVER_HANDLER = 'django_ftpserver.handlers.DjangoFTPHandler'
FTPSERVER_TLSHANDLER = 'django_ftpserver.handlers.DjangoTLS_FTPHandler'