Mail schemes updated auto system
This commit is contained in:
@@ -9,32 +9,29 @@ class OllamaService {
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Ollama service with settings from database
|
||||
*/
|
||||
async initialize() {
|
||||
if (this.initialized && this.serverUrl && this.model) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const serverUrlSetting = await Settings.findOne({
|
||||
where: { key: 'ollama_server_url' },
|
||||
});
|
||||
const modelSetting = await Settings.findOne({
|
||||
where: { key: 'ollama_model' },
|
||||
const settings = await Settings.findAll();
|
||||
const settingsMap = {};
|
||||
settings.forEach(s => {
|
||||
settingsMap[s.key] = s.value;
|
||||
});
|
||||
|
||||
this.serverUrl = serverUrlSetting?.value || process.env.OLLAMA_URL || 'http://localhost:11434';
|
||||
this.model = modelSetting?.value || process.env.OLLAMA_MODEL || 'llama3.2';
|
||||
|
||||
this.serverUrl = settingsMap['ollama_server_url'] || 'http://localhost:11434';
|
||||
this.model = settingsMap['ollama_model'] || 'llama3.2:latest';
|
||||
this.initialized = true;
|
||||
logger.info(`Ollama service initialized: ${this.serverUrl} with model ${this.model}`);
|
||||
|
||||
logger.info(`Ollama initialized: ${this.serverUrl}, model: ${this.model}`);
|
||||
} catch (error) {
|
||||
logger.error('Failed to initialize Ollama service:', error);
|
||||
throw error;
|
||||
logger.error('Failed to initialize Ollama:', error.message);
|
||||
throw new Error('Ollama ayarları yüklenemedi');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test Ollama connection
|
||||
*/
|
||||
async testConnection() {
|
||||
if (!this.initialized) {
|
||||
await this.initialize();
|
||||
@@ -45,24 +42,22 @@ class OllamaService {
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
const models = response.data.models || [];
|
||||
|
||||
return {
|
||||
success: true,
|
||||
models: response.data.models || [],
|
||||
message: 'Ollama bağlantısı başarılı',
|
||||
models: models,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Ollama connection test failed:', error.message);
|
||||
return {
|
||||
success: false,
|
||||
error: error.message,
|
||||
message: 'Ollama sunucusuna bağlanılamadı',
|
||||
message: 'Ollama bağlantısı başarısız: ' + error.message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List available models
|
||||
*/
|
||||
async listModels() {
|
||||
if (!this.initialized) {
|
||||
await this.initialize();
|
||||
@@ -80,23 +75,19 @@ class OllamaService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate mail template using Ollama
|
||||
* @param {Object} params - Template generation parameters
|
||||
* @param {string} params.company_name - Target company name
|
||||
* @param {string} params.scenario - Phishing scenario type
|
||||
* @param {string} params.employee_info - Employee information (optional)
|
||||
* @param {string} params.custom_prompt - Custom instructions (optional)
|
||||
*/
|
||||
async generateMailTemplate(params) {
|
||||
if (!this.initialized) {
|
||||
await this.initialize();
|
||||
}
|
||||
|
||||
const { company_name, scenario, employee_info, custom_prompt } = params;
|
||||
const { company_name, scenario, employee_info, custom_prompt, generate_html = false } = params;
|
||||
|
||||
// Build the prompt
|
||||
const systemPrompt = `Sen profesyonel bir siber güvenlik uzmanısın ve şirketler için phishing farkındalık testi mail şablonları oluşturuyorsun.
|
||||
// Build the prompt based on mode
|
||||
let systemPrompt, userPrompt;
|
||||
|
||||
if (generate_html) {
|
||||
// Full HTML generation mode
|
||||
systemPrompt = `Sen profesyonel bir siber güvenlik uzmanısın ve şirketler için phishing farkındalık testi mail şablonları oluşturuyorsun.
|
||||
|
||||
GÖREV: Gerçekçi, ikna edici ve profesyonel phishing test mailleri oluştur.
|
||||
|
||||
@@ -106,42 +97,75 @@ KURALLAR:
|
||||
3. İkna edici ve inandırıcı olmalı
|
||||
4. Türkçe dil bilgisi ve imla kurallarına uygun olmalı
|
||||
5. Kullanıcıyı aciliyet hissi ile harekete geçirmeli
|
||||
6. Şirket logosu/branding için placeholder kullan
|
||||
|
||||
ZORUNLU PLACEHOLDER'LAR:
|
||||
- {{company_name}} - Şirket adı
|
||||
- {{employee_name}} - Çalışan adı (varsa "Sayın {{employee_name}}", yoksa "Sayın Yetkili")
|
||||
- {{tracking_url}} - Tıklama linki (button veya link olarak)
|
||||
- {{employee_name}} - Çalışan adı
|
||||
- {{tracking_url}} - Tıklama linki
|
||||
|
||||
YANIT FORMATI: Sadece ve sadece JSON, hiçbir ek açıklama yok!`;
|
||||
YANIT FORMATI: Sadece JSON!`;
|
||||
|
||||
let userPrompt = `Aşağıdaki bilgilere göre profesyonel bir phishing test mail şablonu oluştur:
|
||||
userPrompt = `Aşağıdaki bilgilere göre profesyonel bir phishing test mail şablonu oluştur:
|
||||
|
||||
📌 HEDEF ŞİRKET: ${company_name}
|
||||
📌 SENARYO: ${scenario}`;
|
||||
|
||||
if (employee_info) {
|
||||
if (employee_info) userPrompt += `\n📌 HEDEF KİTLE: ${employee_info}`;
|
||||
if (custom_prompt) userPrompt += `\n📌 ÖZEL TALİMATLAR: ${custom_prompt}`;
|
||||
|
||||
userPrompt += `
|
||||
📌 HEDEF KİTLE: ${employee_info}`;
|
||||
}
|
||||
|
||||
if (custom_prompt) {
|
||||
userPrompt += `
|
||||
📌 ÖZEL TALİMATLAR: ${custom_prompt}`;
|
||||
}
|
||||
|
||||
userPrompt += `
|
||||
|
||||
JSON YANIT FORMATI (AYNEN BU YAPIDA):
|
||||
JSON YANIT FORMATI:
|
||||
{
|
||||
"subject": "İkna edici mail konusu buraya (max 70 karakter)",
|
||||
"body": "<!DOCTYPE html><html><head><meta charset='UTF-8'><style>body{font-family:Arial,sans-serif;line-height:1.6;color:#333;max-width:600px;margin:0 auto;padding:20px;}h2{color:#d32f2f;}.button{display:inline-block;padding:12px 30px;background:#d32f2f;color:white;text-decoration:none;border-radius:5px;margin:20px 0;}.footer{font-size:12px;color:#666;margin-top:30px;border-top:1px solid #ddd;padding-top:15px;}</style></head><body><h2>Başlık</h2><p>Sayın {{employee_name}},</p><p>Mail içeriği buraya - ikna edici ve aciliyet vurgulu</p><a href='{{tracking_url}}' class='button'>Butona tıklat</a><div class='footer'>{{company_name}} © 2024</div></body></html>"
|
||||
"subject": "İkna edici mail konusu (max 70 karakter)",
|
||||
"body": "<!DOCTYPE html><html><head><meta charset='UTF-8'><style>body{font-family:Arial,sans-serif;line-height:1.6;color:#333;max-width:600px;margin:0 auto;padding:20px;}h2{color:#d32f2f;}.button{display:inline-block;padding:12px 30px;background:#d32f2f;color:white;text-decoration:none;border-radius:5px;margin:20px 0;}</style></head><body><h2>Başlık</h2><p>Sayın {{employee_name}},</p><p>İçerik</p><a href='{{tracking_url}}' class='button'>Tıklayın</a></body></html>"
|
||||
}
|
||||
|
||||
⚠️ SADECE JSON DÖNDÜR! Açıklama, not, yorum YAZMA!
|
||||
⚠️ Body içinde CSS stillendir, responsive yap!
|
||||
⚠️ Konuyu çekici ve acil yap!
|
||||
⚠️ HTML'i tam ve geçerli oluştur!`;
|
||||
⚠️ SADECE JSON DÖNDÜR!`;
|
||||
|
||||
} else {
|
||||
// Text-only generation mode (RECOMMENDED)
|
||||
systemPrompt = `Sen profesyonel bir siber güvenlik uzmanısın ve phishing test mail içerikleri yazıyorsun.
|
||||
|
||||
GÖREV: İkna edici, gerçekçi ve profesyonel mail içerikleri yaz.
|
||||
|
||||
KURALLAR:
|
||||
1. Gerçek şirket maillerine benzer dil ve ton kullan
|
||||
2. İkna edici ve inandırıcı ol
|
||||
3. Türkçe dil bilgisi ve imla kurallarına uygun yaz
|
||||
4. Kullanıcıyı aciliyet hissi ile harekete geçir
|
||||
5. SADECE METİN İÇERİĞİ yaz, HTML TAG'LERİ KULLANMA!
|
||||
|
||||
ZORUNLU PLACEHOLDER'LAR:
|
||||
- {{company_name}} - Şirket adı
|
||||
- {{employee_name}} - Çalışan adı
|
||||
- {{tracking_url}} - Link metni (örn: "buraya tıklayın", "hesabınızı doğrulayın")
|
||||
|
||||
YANIT FORMATI: Sadece JSON!`;
|
||||
|
||||
userPrompt = `Aşağıdaki bilgilere göre profesyonel bir phishing test mail içeriği yaz:
|
||||
|
||||
📌 HEDEF ŞİRKET: ${company_name}
|
||||
📌 SENARYO: ${scenario}`;
|
||||
|
||||
if (employee_info) userPrompt += `\n📌 HEDEF KİTLE: ${employee_info}`;
|
||||
if (custom_prompt) userPrompt += `\n📌 ÖZEL TALİMATLAR: ${custom_prompt}`;
|
||||
|
||||
userPrompt += `
|
||||
|
||||
JSON YANIT FORMATI:
|
||||
{
|
||||
"subject": "İkna edici mail konusu (max 70 karakter)",
|
||||
"body": "Mail içeriği buraya. Sayın {{employee_name}}, [mesajın içeriği]. Link metni için {{tracking_url}} placeholder'ını kullan. İmza kısmı."
|
||||
}
|
||||
|
||||
⚠️ ÖNEMLİ:
|
||||
- Body içinde HTML TAG kullanma (<p>, <div> gibi)!
|
||||
- Sadece düz metin yaz!
|
||||
- Satır atlamak için sadece yeni satır kullan!
|
||||
- {{tracking_url}} placeholder'ını link metni içinde kullan (örn: "{{tracking_url}} buraya tıklayın")
|
||||
- SADECE JSON DÖNDÜR!`;
|
||||
}
|
||||
|
||||
try {
|
||||
logger.info(`Generating template for company: ${company_name}, scenario: ${scenario}`);
|
||||
@@ -201,11 +225,20 @@ JSON YANIT FORMATI (AYNEN BU YAPIDA):
|
||||
templateData.subject = subject;
|
||||
templateData.body = body;
|
||||
|
||||
// If generate_html is false, wrap the content in our template
|
||||
let finalBody = body;
|
||||
if (!generate_html) {
|
||||
const theme = params.template_theme || 'red';
|
||||
finalBody = this.wrapInTemplate(body, subject, theme);
|
||||
}
|
||||
|
||||
return {
|
||||
subject_template: templateData.subject,
|
||||
body_template: templateData.body,
|
||||
body_template: finalBody,
|
||||
generated_by: 'ollama',
|
||||
model: this.model,
|
||||
html_generated: generate_html,
|
||||
theme: params.template_theme || 'red',
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Failed to generate template with Ollama:', error.message);
|
||||
@@ -213,9 +246,180 @@ JSON YANIT FORMATI (AYNEN BU YAPIDA):
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a simple text completion
|
||||
*/
|
||||
getTemplateStyles(theme = 'red') {
|
||||
const themes = {
|
||||
red: {
|
||||
name: 'Kırmızı (Acil/Uyarı)',
|
||||
gradient: 'linear-gradient(135deg, #e53935 0%, #c62828 100%)',
|
||||
button: '#e53935',
|
||||
buttonHover: '#c62828',
|
||||
accent: '#e53935',
|
||||
},
|
||||
green: {
|
||||
name: 'Yeşil (Başarı/Onay)',
|
||||
gradient: 'linear-gradient(135deg, #43a047 0%, #2e7d32 100%)',
|
||||
button: '#43a047',
|
||||
buttonHover: '#2e7d32',
|
||||
accent: '#43a047',
|
||||
},
|
||||
blue: {
|
||||
name: 'Mavi (Kurumsal)',
|
||||
gradient: 'linear-gradient(135deg, #1e88e5 0%, #1565c0 100%)',
|
||||
button: '#1e88e5',
|
||||
buttonHover: '#1565c0',
|
||||
accent: '#1e88e5',
|
||||
},
|
||||
purple: {
|
||||
name: 'Mor (Premium)',
|
||||
gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||||
button: '#667eea',
|
||||
buttonHover: '#5568d3',
|
||||
accent: '#667eea',
|
||||
},
|
||||
orange: {
|
||||
name: 'Turuncu (Dikkat)',
|
||||
gradient: 'linear-gradient(135deg, #fb8c00 0%, #ef6c00 100%)',
|
||||
button: '#fb8c00',
|
||||
buttonHover: '#ef6c00',
|
||||
accent: '#fb8c00',
|
||||
},
|
||||
dark: {
|
||||
name: 'Siyah (Ciddi)',
|
||||
gradient: 'linear-gradient(135deg, #37474f 0%, #263238 100%)',
|
||||
button: '#37474f',
|
||||
buttonHover: '#263238',
|
||||
accent: '#37474f',
|
||||
},
|
||||
};
|
||||
|
||||
return themes[theme] || themes.red;
|
||||
}
|
||||
|
||||
wrapInTemplate(textContent, subject, theme = 'red') {
|
||||
const style = this.getTemplateStyles(theme);
|
||||
|
||||
// Convert text to HTML paragraphs
|
||||
const paragraphs = textContent
|
||||
.split('\n\n')
|
||||
.filter(p => p.trim())
|
||||
.map(p => {
|
||||
// Replace {{tracking_url}} placeholder with styled link
|
||||
if (p.includes('{{tracking_url}}')) {
|
||||
return `<p>${p.replace(/\{\{tracking_url\}\}/g, '<a href="{{tracking_url}}" class="button">Buraya Tıklayın</a>')}</p>`;
|
||||
}
|
||||
return `<p>${p}</p>`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="tr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>${subject}</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
background-color: #f5f5f5;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.container {
|
||||
max-width: 600px;
|
||||
margin: 20px auto;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
.header {
|
||||
background: ${style.gradient};
|
||||
color: white;
|
||||
padding: 30px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.header h1 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.content {
|
||||
padding: 30px;
|
||||
}
|
||||
.content p {
|
||||
margin: 0 0 15px 0;
|
||||
color: #555;
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 14px 32px;
|
||||
background: ${style.button};
|
||||
color: white !important;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
margin: 20px 0;
|
||||
font-weight: 600;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
.button:hover {
|
||||
background: ${style.buttonHover};
|
||||
}
|
||||
.footer {
|
||||
background: #f8f9fa;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
border-top: 1px solid #e0e0e0;
|
||||
}
|
||||
.warning {
|
||||
background: #fff3cd;
|
||||
border-left: 4px solid ${style.accent};
|
||||
padding: 15px;
|
||||
margin: 20px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
@media only screen and (max-width: 600px) {
|
||||
.container {
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.content {
|
||||
padding: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h1>{{company_name}}</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
${paragraphs}
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>© 2024 {{company_name}}. Tüm hakları saklıdır.</p>
|
||||
<p style="margin-top: 10px; font-size: 11px;">Bu mail {{company_name}} tarafından gönderilmiştir.</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
getAvailableThemes() {
|
||||
return [
|
||||
{ value: 'red', label: '🔴 Kırmızı (Acil/Uyarı)', description: 'Acil durumlar, güvenlik uyarıları' },
|
||||
{ value: 'green', label: '🟢 Yeşil (Başarı/Onay)', description: 'Onay mailleri, başarı bildirimleri' },
|
||||
{ value: 'blue', label: '🔵 Mavi (Kurumsal)', description: 'Resmi kurumsal mailler' },
|
||||
{ value: 'purple', label: '🟣 Mor (Premium)', description: 'Özel teklifler, premium içerik' },
|
||||
{ value: 'orange', label: '🟠 Turuncu (Dikkat)', description: 'Bildirimler, hatırlatmalar' },
|
||||
{ value: 'dark', label: '⚫ Siyah (Ciddi)', description: 'Ciddi/resmi konular' },
|
||||
];
|
||||
}
|
||||
|
||||
async generate(prompt) {
|
||||
if (!this.initialized) {
|
||||
await this.initialize();
|
||||
@@ -243,4 +447,3 @@ JSON YANIT FORMATI (AYNEN BU YAPIDA):
|
||||
}
|
||||
|
||||
module.exports = new OllamaService();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user