Всем доброго дня.
Долго думал о том с чего начать статью, и как ее преподнести.
Долго думал стоит ли... Но решился и пишу....
Итак начнем с того что спам это не только вебмайлинг смтп и какие-то общепринятые понятия.
Спам это постоянный поиск- поиск инбокса, поиск того какое письмо сработает сегодня.
Вот... дохрена воды помоему. Это не обучение спаму) Это помощь новичкам и тем кто в тупике что стоит иногда просто оглянуться.
Итак начнем, существуют разные crm системы. Будет без линков чтобы хотябы прожило чуть чуть.
Работать мы будем с системой
freshworks.
Заходим в аккаунт.
Переходим во
.freshdesk.com
Идем в профиль и смотрим апи ключ.
Код для того чтобы узнать лимиты:
Разные аккаунты, дают разный лимит.
После того как все хорошо, нашли подходящий аккаунт узнали нужную информацию переходим ко второму коду.
Этот код будет отпавлять письма, совсем уж халявы не получиться надо данный код подстраивать под каждый аккаунт в зависимости от того что именно требуется отправлять, аттачи и так далее.
И не спрашивайте за инбокс....
Долго думал о том с чего начать статью, и как ее преподнести.
Долго думал стоит ли... Но решился и пишу....
Итак начнем с того что спам это не только вебмайлинг смтп и какие-то общепринятые понятия.
Спам это постоянный поиск- поиск инбокса, поиск того какое письмо сработает сегодня.
Вот... дохрена воды помоему. Это не обучение спаму) Это помощь новичкам и тем кто в тупике что стоит иногда просто оглянуться.
Итак начнем, существуют разные crm системы. Будет без линков чтобы хотябы прожило чуть чуть.
Работать мы будем с системой
Вы должны провести 60 дней на форуме для просмотра контента.
freshworks.
Заходим в аккаунт.
Переходим во
Вы должны провести 60 дней на форуме для просмотра контента.
.freshdesk.com
Идем в профиль и смотрим апи ключ.
Код для того чтобы узнать лимиты:
Вы должны провести 60 дней на форуме для просмотра контента.
Python:
import requests
from requests.auth import HTTPBasicAuth
#Заменить на свое.
domain = "respshophelp.freshdesk.com"
api_key = "k9gmiYZS8oRbOc0leYI"
ticket_id = 152109 #Обязательно тикет который использвался почтой.
ticket_url = f"https://{domain}/api/v2/tickets/{ticket_id}"
auth = HTTPBasicAuth(api_key, "X")
ticket_response = requests.get(ticket_url, auth=auth)
if ticket_response.status_code == 200:
ticket_info = ticket_response.json()
email_config_id = ticket_info.get('email_config_id')
group_id = ticket_info.get('group_id')
print(f"Email Config ID: {email_config_id}")
print(f"Group ID: {group_id}")
else:
print(f"Failed to retrieve ticket: {ticket_response.status_code}, {ticket_response.text}")
rate_limit_url = f"https://{domain}/api/v2/tickets"
rate_limit_response = requests.get(rate_limit_url, auth=auth)
if rate_limit_response.status_code == 200:
rate_limit_per_minute = rate_limit_response.headers.get('x-ratelimit-limit')
rate_limit_remaining = rate_limit_response.headers.get('x-ratelimit-remaining')
rate_limit_reset = rate_limit_response.headers.get('x-ratelimit-reset')
print(f"Rate Limit per Minute: {rate_limit_per_minute}")
print(f"Rate Limit Remaining in Current Window: {rate_limit_remaining}")
print(f"Rate Limit Reset Time (in seconds): {rate_limit_reset}")
else:
print(f"Failed to retrieve rate limit information: {rate_limit_response.status_code}, {rate_limit_response.text}")
Разные аккаунты, дают разный лимит.
После того как все хорошо, нашли подходящий аккаунт узнали нужную информацию переходим ко второму коду.
Этот код будет отпавлять письма, совсем уж халявы не получиться надо данный код подстраивать под каждый аккаунт в зависимости от того что именно требуется отправлять, аттачи и так далее.
Вы должны провести 60 дней на форуме для просмотра контента.
Код:
import csv
import random
import requests
from requests.auth import HTTPBasicAuth
from concurrent.futures import ThreadPoolExecutor
import time
from collections import deque
from datetime import datetime
# Replace with your Freshdesk domain and API key
domain = "respshophelp.freshdesk.com"
api_key = "k9gmiYZS8oRbOc0leYI"
auth = HTTPBasicAuth(api_key, "X")
# Email config and group IDs
email_config_id = 66000073222
group_id = 66000086941
# Initialize a deque to track send times
send_times = deque()
links = [
"https://google.com",
"https://google.com"
]
def generate_random_style():
colors = [
'#0d6efd', '#6610f2', '#6f42c1', '#d63384', '#dc3545', '#fd7e14',
'#ffc107', '#28a745', '#20c997', '#17a2b8', '#007bff', '#6c757d',
'#343a40', '#f8f9fa', '#e9ecef', '#f5f5f5', '#dee2e6', '#ced4da'
]
fonts = [
'Arial', 'Verdana', 'Georgia', 'Tahoma', 'Trebuchet MS', 'Open Sans', 'Helvetica',
'Courier New', 'Lucida Console', 'Garamond', 'Palatino Linotype', 'Book Antiqua',
'Impact', 'Segoe UI', 'Roboto', 'Lato', 'Montserrat', 'Ubuntu', 'Nunito', 'Poppins'
]
padding = f"{random.randint(10, 30)}px {random.randint(20, 40)}px"
border_radius = f"{random.randint(5, 20)}px"
text_align = random.choice(['center', 'left', 'right'])
border_style = random.choice(['solid', 'dotted', 'dashed', 'double'])
border_width = f"{random.randint(1, 3)}px"
border_color = random.choice(colors)
box_shadow = f"0px {random.randint(1, 4)}px {random.randint(5, 15)}px rgba(0, 0, 0, 0.1)"
return {
'color': random.choice(colors),
'font': random.choice(fonts),
'padding': padding,
'border_radius': border_radius,
'text_align': text_align,
'border_style': border_style,
'border_width': border_width,
'border_color': border_color,
'box_shadow': box_shadow,
'button_bg_color': random.choice(colors),
'button_text_color': '#ffffff'
}
def fetch_ticket_type():
ticket_types = [
"Question", "Problema con datos inconsistentes y comunicaciones",
"Error del cliente", "Solicitud de modificación de sistema",
"Cliente solicita cambios (Versión, configuracion)", "Posnet, MPago y Hardware",
"Cerrado por estar duplicado", "Cliente consulta", "Reabierto",
"A revisar por Sistemas", "Error a corregir.", "Nueva instalación",
"Guardia", "Aplicaciones accesorias (Certif. FAE, WebHost, CaldenOn, TF, CVirtual)"
]
print("Available Ticket Types:")
for i, t_type in enumerate(ticket_types, start=1):
print(f"{i}. {t_type}")
choice = int(input("Select a ticket type by number: ")) - 1
return ticket_types[choice]
def create_beautiful_name(name):
return name.title() # Capitalizes the first letter of each word
def display_rate_limits(response):
rate_limit = response.headers.get('X-RateLimit-Limit')
rate_limit_remaining = int(response.headers.get('X-RateLimit-Remaining', '0'))
rate_limit_reset = response.headers.get('X-RateLimit-Reset')
print("Rate Limits:")
print(f"Rate Limit: {rate_limit}")
print(f"Rate Limit Remaining: {rate_limit_remaining}")
print(f"Rate Limit Reset: {rate_limit_reset}")
return rate_limit_remaining
def enforce_rate_limit(rate_limit_remaining):
global send_times
if len(send_times) >= 250:
print("Sent 200 emails. Waiting 1 minute before continuing...")
time.sleep(60)
send_times.clear() # Clear the deque after waiting
if rate_limit_remaining < 10:
print("Rate limit remaining is less than 10. Waiting 10 minutes before checking again...")
time.sleep(600)
def prompt_to_continue():
while True:
choice = input("No more emails in the file. Would you like to add more rows or stop the campaign? (add/stop): ").strip().lower()
if choice == "add":
return True
elif choice == "stop":
return False
else:
print("Invalid choice. Please enter 'add' or 'stop'.")
def send_email(row, group_id, email_config_id, ticket_type):
email = None # Initialize email variable
try:
email = row['email']
name = create_beautiful_name(row['name'])
address = row['adress'] if row['zip'] else 'N/A'
city = row['city'] if row['zip'] else 'N/A'
zip_code = row['zip'] if row['zip'] else 'N/A'
state = row['state'] if row['state'] else 'N/A'
country = row['country'] if row['state'] else 'N/A'
styles = generate_random_style()
# Randomly select a link from the list
selected_link = random.choice(links)
# Create a personalized subject
subject = f"{name}, Delivery parcel.."
# HTML email template with inline styles
html_template = f"""
<!DOCTYPE html>
<html lang="en">
<head>
"""
# Set the correct product vendor value
product_vendor = "Freshdesk" # Replace with the correct value as per your requirements
# Data for the outbound email
email_data = {
"email": email,
"subject": subject,
"description": html_template,
"priority": 1,
"type": ticket_type,
"group_id": int(group_id),
"email_config_id": int(email_config_id),
}
url = f"https://{domain}/api/v2/tickets/outbound_email"
# Sending the POST request to create the outbound email
response = requests.post(url, auth=auth, json=email_data)
# Display rate limits after sending each email
rate_limit_remaining = display_rate_limits(response)
if response.status_code == 201:
print(f"Outbound email sent successfully to {email}.")
send_times.append(datetime.now()) # Track the time this email was sent
# Enforce rate limit after sending the email
enforce_rate_limit(rate_limit_remaining)
else:
print(f"Failed to send outbound email to {email}: {response.status_code}, {response.text}")
except KeyError as e:
print(f"KeyError: Missing key {str(e)} in the CSV file for {email or 'unknown email'}.")
except Exception as e:
print(f"Error occurred for {email or 'unknown email'}: {str(e)}")
# Fetch ticket type
ticket_type = fetch_ticket_type()
# Path to your CSV file
csv_file_path = r'C:\Users\Administrator\Desktop\contacts.csv'
# Main loop to read the CSV file and send emails concurrently
while True:
with open(csv_file_path, mode='r', encoding='ISO-8859-1') as file:
csv_reader = csv.DictReader(file)
with ThreadPoolExecutor(max_workers=2) as executor:
futures = [executor.submit(send_email, row, group_id, email_config_id, ticket_type) for row in csv_reader]
# Ensure all threads are completed
for future in futures:
try:
future.result() # Re-raise any exception that occurred in the thread
except Exception as e:
print(f"An error occurred during execution: {str(e)}")
# Prompt to continue or stop when the end of the file is reached
if not prompt_to_continue():
print("Campaign stopped.")
break # Exit the loop if the user decides to stop
print("All emails processed.")
И не спрашивайте за инбокс....
