Job Application System
A simple, accessible Flask web application for job applications with email-based resume functionality and file uploads.
Features
- Multi-step application process: 5-page workflow from email capture to confirmation
- Email-based resume: Applicants receive a unique link to resume their application
- Stateful sessions: Applications can be paused and resumed at any time
- File uploads: Support for CV, cover letter, and other documents (up to 3 files, 4 MB each)
- German interface: All user-facing content in German
- File-based storage: No database required - uses YAML for data serialization
- Accessible design: Minimal CSS, no JavaScript required, keyboard-friendly
- Validation: Comprehensive server-side validation for all inputs
Application Workflow
- Email Capture: User enters email and receives a resume link
- Personal Information: Name, address, phone, birth year, etc.
- Motivation Questions: Current job situation, motivation, qualifications, salary expectations
- Document Upload: Upload up to 3 documents (CV, cover letter, etc.)
- Confirmation: Success message with next steps
Technology Stack
- Python 3
- Flask 3.0.0
- PyYAML for data serialization
- Flask-Mail for email sending
- Minimal CSS for styling
- No JavaScript required
Installation
Prerequisites
- Python 3.8 or higher
- pip (Python package manager)
Setup Steps
-
Clone or download this repository
-
Create a virtual environment (recommended):
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate -
Install dependencies:
pip install -r requirements.txt -
Configure environment variables:
- Copy
.env.exampleto.env:cp .env.example .env - Edit
.envand configure your settings:SECRET_KEY=your-secret-key-here MAIL_SERVER=smtp.gmail.com MAIL_PORT=587 MAIL_USE_TLS=True MAIL_USERNAME=your-email@example.com MAIL_PASSWORD=your-app-password MAIL_DEFAULT_SENDER=noreply@example.com COMPANY_NAME=Your Company Name
- Copy
Email Configuration
For Gmail, you need to:
- Enable 2-factor authentication on your Google account
- Generate an "App Password" at https://myaccount.google.com/apppasswords
- Use the app password (not your regular password) in
MAIL_PASSWORD
For other email providers, adjust MAIL_SERVER and MAIL_PORT accordingly.
Running the Application
Development Mode
python app.py
The application will run at http://127.0.0.1:5000
Production Deployment
For production, use a WSGI server like Gunicorn:
-
Install Gunicorn:
pip install gunicorn -
Run with Gunicorn:
gunicorn -w 4 -b 0.0.0.0:8000 app:app -
Use a reverse proxy (e.g., Nginx) in front of Gunicorn
Usage
Linking from Job Postings
Link to the application with a job parameter:
https://your-domain.com/apply?job=JuniorMarketingAssistant
The job parameter will be displayed throughout the application and stored with the application data.
Resume Functionality
When applicants enter their email, they receive a link like:
https://your-domain.com/resume/{session-id}
This link allows them to resume their application at any time.
File Structure
.
├── app.py # Main Flask application
├── config.py # Configuration settings
├── requirements.txt # Python dependencies
├── .env.example # Example environment variables
├── README.md # This file
├── templates/ # HTML templates
│ ├── base.html
│ ├── page1_email.html
│ ├── page2_personal.html
│ ├── page3_motivation.html
│ ├── page4_upload.html
│ └── page5_confirmation.html
├── static/ # Static files
│ └── style.css
└── applications/ # Application data (created automatically)
└── {session-id}/
├── data.yaml
└── attachments/
Data Storage
Each application is stored in its own folder under ./applications/{session-id}/:
data.yaml: Application data (personal info, answers, metadata)attachments/: Uploaded documents
Example data.yaml structure:
session_id: "abc123-def456-..."
email: "applicant@example.com"
job_name: "Junior Marketing Assistant"
current_page: 4
created_at: "2025-01-15T10:30:00"
updated_at: "2025-01-15T11:45:00"
personal_info:
name: "Müller"
firstname: "Anna"
address: "Hauptstrasse 123"
zip_code: "8001"
city: "Zürich"
phone: "+41 79 123 45 67"
birth_year: "1990"
civil_status: "ledig"
motivation_answers:
current_job: "..."
motivation: "..."
qualifications: "..."
salary: "..."
uploaded_files:
- original_name: "CV.pdf"
stored_name: "20250115_103000_CV.pdf"
uploaded_at: "2025-01-15T10:30:00"
size: 1048576
Validation Rules
Email (Page 1)
- Valid email format required
Personal Information (Page 2)
- Name: Required, max 255 characters
- Firstname: Required, max 255 characters
- Address: Required, max 255 characters
- ZIP Code: Required, numeric, max 10 digits
- City: Required, max 255 characters
- Phone: Required, international format (e.g., +41 79 123 45 67)
- Birth Year: Required, 4 digits, between 1940 and 2010
- Civil Status: Optional, max 255 characters
Motivation (Page 3)
- All fields optional
- Each textarea limited to 3000 characters (~1 A4 page)
File Upload (Page 4)
- Maximum 3 files
- Maximum 4 MB per file
- Allowed formats: PDF, DOC, DOCX, TXT, JPG, JPEG, PNG
Security Considerations
- Session IDs use cryptographically secure UUIDs
- File uploads are validated for size and type
- Filenames are sanitized to prevent path traversal
- All validation is server-side
- Email configuration uses environment variables
Customization
Changing Text Limits
Edit config.py:
MAX_STRING_LENGTH = 255
MAX_TEXT_AREA_LENGTH = 3000
MAX_FILE_SIZE = 4 * 1024 * 1024 # 4 MB
MAX_FILES = 3
Changing Allowed File Types
Edit config.py:
ALLOWED_EXTENSIONS = {'pdf', 'doc', 'docx', 'txt', 'jpg', 'jpeg', 'png'}
Translating to Another Language
Edit all templates in ./templates/ - they contain German text that can be translated.
Troubleshooting
Email not sending
- Check your email credentials in
.env - For Gmail, ensure you're using an app password, not your regular password
- Check that
MAIL_USE_TLSis set correctly for your email provider - Check application logs for error messages
File upload errors
- Ensure the
./applications/folder is writable - Check file size limits in your web server configuration
- Verify allowed file extensions in
config.py
Session not resuming
- Check that the
./applications/{session-id}/folder exists - Verify that
data.yamlis valid YAML format - Check application logs for errors
License
This project is provided as-is for use in job application processes.
Support
For issues or questions, please contact your system administrator.